Hi Mauro, 2016-06-22 21:13 GMT+02:00 Mauro: > > A REPL session of mine trying to figure out how to make that macro would > look something like this: > > julia> ex = :(f(x, y, z, zz)) # this is what is passed into the macro > :(f(x,y,z,zz)) > > julia> xdump(ex) # xdump is nice to get an overview of nested > datastructures > Expr > head: Symbol call > args: Array(Any,(5,)) > 1: Symbol f > 2: Symbol x > 3: Symbol y > 4: Symbol z > 5: Symbol zz > typ: Any::DataType <: Any >
I knew and used "dump" but not "xdump". I've seen that the latter has been deprecated in favor of the former in Julia 0.5. > julia> target = :(f([x.re, y.re, z.re, zz.re].^2 + [x.im, y.im, z.im, > zz.im])) # this is your target > :(f([x.re,y.re,z.re,zz.re] .^ 2 + [x.im,y.im,z.im,zz.im])) > > julia> xdump(target) > Expr > head: Symbol call > args: Array(Any,(2,)) > 1: Symbol f > 2: Expr > head: Symbol call > args: Array(Any,(3,)) > 1: Symbol + > 2: Expr > head: Symbol call > args: Array(Any,(3,)) > typ: Any::DataType <: Any > 3: Expr > head: Symbol vect > args: Array(Any,(4,)) > typ: Any::DataType <: Any > typ: Any::DataType <: Any > typ: Any::DataType <: Any > > > Now, writing the macro is really an exercise in manipulating nested data > structures. With the added bonus that there are convenient constructors > for those datastructures, namely expression such as e.g. :(z = 4 +7). > > julia> fn = ex.args[1] # extract the name of the function > :f > > julia> args = ex.args[2:end] # its arguments > 4-element Array{Any,1}: > :x > :y > :z > :zz > > julia> ar1 =:([]) # build up the first array > :([]) > > julia> ar1.head # check > :vect > > julia> [push!(ar1.args, :($(args[i]).re)) for i=1:length(args)] #add the > elements > 4-element Array{Any,1}: > Any[:(x.re),:(y.re),:(z.re),:(zz.re)] > Any[:(x.re),:(y.re),:(z.re),:(zz.re)] > Any[:(x.re),:(y.re),:(z.re),:(zz.re)] > Any[:(x.re),:(y.re),:(z.re),:(zz.re)] > > julia> ar1 > :([x.re,y.re,z.re,zz.re]) > > julia> :($ar1^2) # square > :([x.re,y.re,z.re,zz.re] ^ 2) > > etc. > > It takes a bit of practice and patience. Important, as Kristoffer said, > write out and test the code you expect the macro to form (at least until > you become a macro ninja), then write the macro. For instance in one of > my projects I hand wrote all of the code I later built macros to > generate: > https://github.com/mauro3/Traits.jl/blob/master/test/manual-traitdef.jl > Thank you so much, I've been able to change my "@uncertain" macro for Measurements.jl <https://github.com/giordano/Measurements.jl> package following your hints. In the end, the trick was to quote rather than to evaluate the array of arguments. Probably this is a good rule of thumb when writing macros. Bye, Mosè