I agree there should be some standard way of doing this. Here were some discussions on how to pack/unpack parameters: https://groups.google.com/d/msg/julia-users/IQS2mT1ITwU/gEyj6JNJsuAJ https://groups.google.com/d/msg/julia-users/VOg7oew4rEM/YQrNoswKevgJ https://groups.google.com/d/msg/julia-users/j4GPm-vJc2o/ri5uwJT0kcoJ
I recall there was one more thread, which I cannot find anymore, where Stefan argued against this for some reason I cannot remember anymore. And somewhat related: https://groups.google.com/d/msg/julia-users/YP31LM3Qto0/ET-XjN-vQuAJ On Fri, 2015-02-06 at 04:11, Kirill Ignatiev <[email protected]> wrote: > When I have a somewhat complex datatype, I often end up constructing it by > assigning values to local variables, then constructing a value of the > datatype in one go at the end, like "x,y=1,2; Foo(x,y)". When there are > many fields, Haskell's RecordWildcards idea is convenient: there you can > say "Foo{..}", which is equivalent to "Foo(x,y)", where x, y are local > variables. You can also decompose structures the same way: "Foo {..} = v" > is equivalent to "x, y = v.x, v.y" (not haskell syntax). The order of > variables is always correct, and the result is more readable, so long as > you know what the field names are. > > So in julia, it would be convenient to have macros that allow you to > construct a type from local variables, and that allow you to inject a > type's fields into the local environment, just like pattern matching with > record wildcards in haskell, like so: > > macro make(typename) >> datatype = eval(typename) >> @assert isa(datatype, DataType) >> fields = names(datatype) >> esc(Expr(:call, typename, fields...)) >> end >> macro inject(typename, varname) >> datatype = eval(typename) >> @assert isa(datatype, DataType) >> fields = names(datatype) >> esc(Expr(:block, map(f -> :($f = $varname.$f), fields)...)) >> end > > > An example would be > > type Foo; x; y; end >> x = 1 >> y = 2 >> var = @make Foo >> var2 = Foo(3, 4) >> @inject Foo var2 > > @show x, y > > > Any thoughts? The use of "eval" is slightly ugly, but the macro needs to > know the field names of a type when it is expanded, and it cannot be a > function because it needs to use local variables. > > This is not so good for accessing fields of an external julia library, > because you don't really know which fields are present there, but it's > convenient when you have control over the fields yourself. > > Also, how can I get a macro to evaluate an expression in the context of its > caller? Otherwise, the "eval(typename)" is incorrect, and I don't want to > call it as "eval(:(@inject $Foo varfoo))". The type declaration should (I > think) already be known when the macro is expanded.
