Something in your explanation doesn’t really fit with other parts…
Why is that? For one, since computer doesn’t really care about the length of the field name I assume this is to help a human (user or developer) to remember them. The computer only care about the length regarding memory consumption and a
Dict certainly doesn’t help in that regard. Moreover, I don’t think a
Dict can really help you remember it either. Are you creating them, in which case you have to type the field names. Or are you getting it from somewhere, in which case the reader code should have no problem remembering the field names and you shouldn’t have to put them into a
Dict to “remember them”.
So if you are reading from a file, I still don’t really see how
Dict is essential here. The
Dict is at most a slightly different representation of what you get from the file so are you just saying that you are using a
Dict as a generic intermediate format to store the info that you later want to put into your type? Depending on the design, you could be better off not have this step but having this is certainly a valid choice. Is that what you want? (Even if this is the case I still don’t really see how it helps you remember though, especially since there isn’t really any alternative that does require you to remember the field names…)
What I said above doesn’t really affect the way you construct
A but it’ll strongly affect whether you even need to do these and how do you integrate the code if you do need it.
Now onto creating
A. The only way you can create an immutable type is from it’s constructor so if you want to make any generic code you must make some assumptions about the constructor. The only one you can make without special convention in your own code is to assume it has something similar to the default constructor, in which case the only way to do what you want is pretty much
A(d[:mass], d[:velocity], d[:coordinate], d[:time], d[:frequency]) and variances using
get etc to handle missing/default values. You can get the effect of the expression above in many different ways. If this is something that is type stable (i.e. the caller know the type) you can use generated function and generate the expression above based on the input type, sth like this,
julia> :(A($((:(d[$(QuoteNode(f))]) for f in fieldnames(A))...)))
:(A(d[:mass], d[:velocity], d[:coordinate], d[:time], d[:frequency]))
if this is sth like deserialization where the caller doesn’t really know the type (the type is also read from the file, for example) then you can just construct the arguments directly, sth like,
julia> A((d[f] for f in fieldnames(A))...)
A(1, "2.0", [3, 3, 3], (2, 3), 5.0)
which one to pick is strongly depending on what you are doing, as mentioned above.
P.S. many of your field types for
A are not concrete types and you may want to change that.