Hi Stefan,

I agree I would rather use an immutable type, what I am trying to work 
around is the lack of support for some kind of "using" language feature 
similar to how namespaces work but for instances of a user defined 
composite type, that would be ideal. Then I can avoid all the obfuscating 
dot notation to access variables.

type Typename
    a
    b
end

# this would be ideal:
function calculate (value::Typename)
    using value
    a = 1 # complicated algorithm
    b = 2 # complicated algorithm
    return value
end

# warning / error doing this:
function calculateBad1 (value::Typename)
    a::Float64
    using values
    a = 1 # complicated algorithm
    b = 2 # complicated algorithm
    return value
end

# warning / error doing this:
function calculateBad2 (value1::Typename, value2::Typename)
    using value1
    using value2
    a = 1 # complicated algorithm
    b = 2 # complicated algorithm
    return value1
end


On Tuesday, June 10, 2014 1:10:35 AM UTC+8, Stefan Karpinski 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] 
> <javascript:>> 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