Yes I realize now that I jumped the gun on my post. It would definitely be very useful if you could reduce this code
x = point.x y = point.y # do stuff on x and y point.x = x point.y = y by something like @fetch_and_store(Point, :foo, quote #do stuff on x and y end) p = Point(1, 0) foo(p) Where @fetch_and_store creates a function foo(point::Point) that handles all of the setup and storing of variables, but this still requires the type information of Point. On Monday, June 9, 2014 12:43:43 PM UTC-5, Jameson wrote: > > > something's probably wrong. > Like this macro assuming you want to disable optimization of your code and > only work in the global scope without modules. > > I maintain my recommendation of using an immutable type (which allows llvm > to do some additional optimizations) and making a single local variable > with a shorter name for typing repeatedly. > > The only feature somewhat unique to Visual Basic that I liked is the with > block , which is similar to what you are asking. I would love to have this > syntax in Julia too, but I'm not sure it is possible/a good idea. Since it > is just a source transform, it should avoid Stefan's note about the > compile/runtime distinction error. > > On Monday, June 9, 2014, Stefan Karpinski <[email protected] > <javascript:>> wrote: > >> 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? >>>>>> >>>>>> >>
