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?
>>>>
>>>>

Reply via email to