I would appreciate any opinions or thoughts on the following. I want to create a struct and I want one of the fields of the struct to be dependent on the others. Below is how I’ve accomplished this as a first pass.
struct MyStruct
a::Int
b::Real
grid::Matrix{Float64}
end
function MyStruct(a::Int, b::Real)::MyStruct
grid = zeros(Float64, a, a,)
grid[1, 2:end-1] .= b
grid[2:end-1, end] .= b
return MyStruct(a, b, grid)
end
I’m wondering if this implementation is proper or if there is a better or more “julia” way of implementing it.
Edit: I should have made this clearer. I want the grid
to be determined from a
and b
.
a
seems to be redundant since you can infer it from the size of grid? But not a big deal.
However, I would define the struct as
struct MyStruct{T}
a::Int
b::T
grid::Matrix{T}
end
Or
struct MyStruct{B, T}
a::Int
b::B
grid::Matrix{T}
end
Since Real
is not a concrete type and can make the struct slow if you pass it around often. Now the struct size is completely clear from the type signature and the derived types in the body.
2 Likes
To clarify: Do you want grid
to take the values from b
at initialization only or always?
You may also be interested in Parameters.jl
here, which enables keyword-based initialization as well as fields that depend on other fields (search for “Parameter interdependence” from the doc here)
ex.
julia> using Parameters
julia> @with_kw struct foo
a::Int
b::Real
grid::Matrix{Float64} = g(a,b)
end
foo
julia> function g(a,b)
grid = zeros(Float64, a, a,)
grid[1, 2:end-1] .= b
grid[2:end-1, end] .= b
grid
end
g (generic function with 1 method)
julia> x = foo(a=4,b=1.2)
foo
a: Int64 4
b: Float64 1.2
grid: Array{Float64}((4, 4)) [0.0 1.2 1.2 0.0; 0.0 0.0 0.0 1.2; 0.0 0.0 0.0 1.2; 0.0 0.0 0.0 0.0]
julia> x.grid
4×4 Matrix{Float64}:
0.0 1.2 1.2 0.0
0.0 0.0 0.0 1.2
0.0 0.0 0.0 1.2
0.0 0.0 0.0 0.0