Any time there's an eval in what your macro emits, something's probably wrong. In this case, however, you can't really avoid it – largely because you can't do this correctly. The trouble is that the type of the object you want to bind the fields of is a runtime property, but you want to bind variables based on it – which is a compile-time property.
On Mon, Jun 9, 2014 at 12:55 PM, Nathaniel Nicandro < [email protected]> wrote: > Oh, yes I see that now. Then what you could do is quote the call to > names() in your macro expression so the names call is executed in the > calling environment. > > macro fetch(p) > return quote > local vars = names($p) > local ex = Expr(:block) > append!(ex.args, [:($v = $p.$v) for v in vars]) > eval(ex) > end > end > > This is similar to what yo have done at the REPL but it quotes the names() > call so it can get evaluated in the macro calling environment instead of > within the macro itself. ex = Expr(:block) is just another quote block > with a list of expressions to evaluate in ex.args. Note that there is no > need to use esc() here because the eval() call happens in the calling > environment. > > > On Monday, June 9, 2014 10:18:13 AM UTC-5, Andrew Simper wrote: >> >> Yes thanks for pointing that out, but if you look at this thread I >> already got some help with the |> esc for this type of thing over on >> another thread https://groups.google.com/forum/#!topic/julia-users/ >> UvBff9QVKaA , but I started this thread specifically to find out how to >> get write a macro using names(obj) to do the work instead of having to >> write a new fetch macro manually every time I create a new type. >> >> On Monday, June 9, 2014 11:04:12 PM UTC+8, Nathaniel Nicandro wrote: >>> >>> You can use the esc >>> <http://julia.readthedocs.org/en/latest/stdlib/base/?highlight=esc#Base.esc> >>> function >>> that can introduce variables in the calling environment >>> >>> julia> type Point >>> x >>> y >>> end >>> >>> julia> macro fetch(p) >>> variables = quote >>> x = $p.x >>> y = $p.y >>> end >>> return esc(variables) >>> end >>> >>> julia> p = Point(5, 10) >>> Point(5,10) >>> >>> julia> x >>> ERROR: x not defined >>> >>> julia> y >>> ERROR: y not defined >>> >>> julia> @fetch p; >>> >>> julia> x >>> 5 >>> >>> julia> y >>> 10 >>> >>> >>> >>> On Saturday, June 7, 2014 2:35:59 AM UTC-5, Andrew Simper wrote: >>>> >>>> A lot of the time it is good to copy a structure to local variables and >>>> then process on those for efficiency before storing the local values back >>>> to a structure. To help out with this I'm trying to write a macro, so this >>>> is what I would like the end result to be: >>>> >>>> Point >>>> x::Float64 >>>> y::Float64 >>>> end >>>> >>>> function process (p::Point) >>>> local x = p.x; >>>> local y = p.y; >>>> # do some processing on x and y >>>> p.x = x >>>> p.y = y >>>> end >>>> >>>> and I would like write a macro that does this so the end code would >>>> like like: >>>> >>>> function process (p::Point) >>>> @fetch p >>>> # do some processing on x and y >>>> @store p >>>> end >>>> >>>> So far I've got this working at the REPL using: >>>> >>>> point = Point (1, 2) >>>> map (eval, ([:($name = point.$name) for name in names(point)])) >>>> println("x=$(x) y=$(y)") >>>> >>>> which prints out: x=1.0 y=2.0 >>>> >>>> Can someone please help out turning this into a macro? >>>> >>>>
