To be more specific I suppose I should call the variable being passed to
the function "this", so what I am after is good way to write functions that
process on and update state, which can either be immutable or not depending
on what is most efficient for the specific operations:
immutable State
a
b
# ....
z
end
function process (this::State, input)
using this
a = 1 # complicated computation that depends on a, b, c, ... z and input
b = 2 # complicated computation that depends on a, b, c, ... z and input
# ...
z = 26 # complicated computation that depends on a, b, c, ... z and
input
return this
end
This is not just about object oriented like programming, but it is a common
pattern that algorithms share over and over again, so it would be nice to
have a concise (end computationally efficient) way to express this in Julia.
On Tuesday, June 10, 2014 10:49:56 AM UTC+8, Andrew Simper wrote:
>
> 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]> 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?
>>>>>>
>>>>>>
>>