Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set default parameters for mutable structs in Julia?

Is there a way to add default parameters for mutable structs in Julia?

I'm trying to write something like the following:

mutable struct Scale
    # Set default values that will be changed by fit!()
    domain_min::Float64 = 0.0
    domain_max::Float64 = 1.0
    range_min::Float64  = 0.0 
    range_max::Float64  = 1.0
end

function fit!(data::Array)
    # Set struct params here using `data`
end

Is there a way to do this or should I try a different approach?

like image 280
A Poor Avatar asked Jan 28 '21 21:01

A Poor


People also ask

What is the use of type parameters in Julia?

Type parameters may be omitted when they do not need to be referenced or restricted. Julia's type system is designed to be powerful and expressive, yet clear, intuitive and unobtrusive. Many Julia programmers may never feel the need to write code that explicitly uses types.

Are the fields of a struct immutable by default?

I noticed that when a struct is declared, its fields are immutable by default unless the mutable keyword is used. What is the reason for this? Is it good practice to use mutable structs?

Does a mutable struct need to be mutable?

Writing mutable struct Foo makes you ask "does this really need to be mutable?", which is a good thing! Immutable struct types are the closest thing we have to value type structs in other languages. We inline them in arrays in at least some cases, and being immutable makes it much harder to tell whether they are value or reference types.

What is a type object in Julia?

In Julia, type objects also serve as constructor functions: they create new instances of themselves when applied to an argument tuple as a function. This much was already mentioned briefly when composite types were introduced.


Video Answer


3 Answers

This is exactly what Base.@kwdef does:

julia> Base.@kwdef mutable struct Scale
           # Set default values that will be changed by fit!()
           domain_min::Float64 = 0.0
           domain_max::Float64 = 1.0
           range_min::Float64  = 0.0 
           range_max::Float64  = 1.0
       end
Scale

# All parameters to their default values
julia> Scale()
Scale(0.0, 1.0, 0.0, 1.0)

# Specify some parameter(s) using keyword argument(s)
julia> Scale(range_min = 0.5)
Scale(0.0, 1.0, 0.5, 1.0)
like image 153
François Févotte Avatar answered Oct 17 '22 17:10

François Févotte


I prefer using Parameters.jl because it provides also a nicer way the structs are displayed which is much nicer for debugging:

julia> using Parameters

julia> @with_kw struct A          
       a::Int=5                   
       b::String="hello"          
       c::Float64                 
       end;                                 
                                  
julia> A(c=3.5)                   
A                                 
  a: Int64 5                      
  b: String "hello"               
  c: Float64 3.5                  
like image 37
Przemyslaw Szufel Avatar answered Oct 17 '22 18:10

Przemyslaw Szufel


Or you can also just go the long way and define it yourself with constructors, as you would normally do if you want to instantiate it in several possible ways.

mutable struct Scale                                                                                                                                                                                                                          
    # Set default values that will be changed by fit!()
    domain_min::Float64      
    domain_max::Float64      
    range_min::Float64        
    range_max::Float64       
end

# With default values, but no keywords
julia> Scale(dmin=1.,dmax=2.,rmin=1.,rmax=2.) = Scale(dmin, dmax, rmin, rmax)
Scale

julia> Scale(3.,4.)
Scale(3.0, 4.0, 1.0, 2.0)

# With keyword arguments:
julia> Scale(;dmin=1.,dmax=2.,rmin=1.,rmax=2.) = Scale(dmin, dmax, rmin, rmax)
Scale

julia> Scale(rmax=3., rmin=1.2)
Scale(1.0, 2.0, 1.2, 3.0)

Notice the difference between the two constructors, one has a semicolon ; the other not. I would not recommend using both constructors at the same time, this may lead to some confusion.

like image 45
Oskar Avatar answered Oct 17 '22 18:10

Oskar