I am looking at Parameters.jl to reduce the number of inputs to some functions.
How do I add an already-defined parameter to a parameter struct?
For context, one of my functions requires many constants as input: N1, N2, …, which are themselves computed by another function. So I can’t just say
@with_kw struct Para
N1::Int64
end
and give it a value because N1 is already defined.
…and I guess while I’m at it, how would I define an array inside the Para struct? One of the arrays I would try to define is of type StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}. (Can that string be truncated and/or is there a better way to do that?) Similar situation as above, that array is already defined, so I would not give it a value inside the struct.
Unclear what you mean when you say that you can’t do exactly what you have written. Structs pretty much just pack things together when they are created. Parameters.jl just adds some convenience functionality for working with structs.
So your code example defines a struct Para which you can create an instance of by doing Para(N1=N1value) where N1value is whatever value you are trying to give to N1 in the parameter struct. You can get N1value any way you like, no worries that it is a computed constant.
I’m confused by the order of your code. I imagine the use case as:
N1 = func1(inputs) # N1 now has some value from another function
@with_kw struct Para # structure I want to create to group many constants/arrays
N1::Int # N1 is already defined, so I simply want to add it to struct
end
function func2(Para) # function I want to feed some of Para constants/arrays
@unpack N1
# do math using N1
end
I interpret your code as 1) assigning N1 a value, 2) create a struct containing N1, (3) specify value of N1 using Para(N1=N1). This seems redundant, but I’m sure I’m missing something in connecting Parameters usage to my use case.
# N1 = func1(inputs) # I remove this line because N1 as variable and as a field of the Para struct is confusing
@with_kw struct Para # structure I want to create to group many constants/arrays
N1::Int # N1 is already defined, so I simply want to add it to struct
end
p = Para(func1(inputs))
function func2(p) # function I want to feed some of Para constants/arrays
@unpack N1 = p
# do math using N1
end
By the way, it is not necessary to create intermediate structure, you can use NamedTuple
p = (N1 = func1(inputs))
Or even better
N1 = func1(inputs)
p = (; N1) # This is equivalent to the creation of NamedTuple (N1 = N1)
That’s true, but now p1 and p2 are separate tuples, right?
If a separate function required parameters from both, they’d have to be fed in separately.
What I’m really doing is computing grid parameters (step size, number of points, etc.) So I have a function func that looks like gp1,gp2,gp3 = func(inputs), where “gp” are my resulting grid parameters.
I need to compute grid parameters for multiple grids, say a low-res and a high-res one:
Some combination of these will be needed as input to another function. So ideally I could group all gp variables (constants and arrays) into a structure GP, where GP can be the only input to my new function and I can @unpack whatever I need inside it.
That could work, but if I wanted to use the 2nd element of that array, for example, I’d have to call p[1][2], instead of being able to point to a more memorable variable.
Yup, using an array or tuple of values seems like the way to go.
I guess this was a habit carried over from MATLAB, where one could group many already-defined variables into a “structure”: STRUCT.a = a, STRUCT.b = b. I’ll read up on where/when structures are actually the optimal choice.
gplo = NamedTuple{(:gp1lo,:gp2lo,:gp3lo)}(func(inputslo))
gphi = NamedTuple{(:gp1hi,:gp2hi,:gp3hi)}(func(inputshi))
GP = merge(gplo,gphi)
making it straightforward to call any variable GP.gp1lo. Tried to find a way to define GP in one line but decided it wasn’t worth the time at the moment.
I don’t know if this solution optimizes performance, but it is easy to understand for me (took me a while to get a grip on this) and it’s nice to not need external packages.