On Thu, Jul 21, 2016 at 7:02 PM, Marius Millea <mariusmil...@gmail.com> wrote:
>
>
> On Thu, Jul 21, 2016 at 11:37 PM, Cedric St-Jean <cedric.stj...@gmail.com>
> wrote:
>>
>> Neat macro.
>>
>>>
>>> For this though, my macro needs to somehow figure out that "inc" was also
>>> defined with @self (since it shouldn't blindly add self as a first arg so
>>> other non-@self'ed function calls). Is this possible in Julia?
>>
>>
>> You could have a global Set that would contain the names of the functions
>> that were defined with @self. But IMO this is going to bite you at one point
>> or another.
>
>
> Yea certainly a possibility, although even this doesn't seem that robust
> since you're only doing this based on function name, and you don't know if
> its referring to a different function in any given call environment. I'm
> starting to doubt its truly possible at compile time, although still
> thinking....

No it's not.

>
>
>
>>
>>
>> FYI Mauro's package has something similar.
>
>
> Some interesting stuff in there, thanks!
>
>>
>>
>> I would suggest using a global variable, if you want to avoid explicitly
>> passing `self` all over the place. It would look like this:
>>
>> const self = Array{mytype}()   # trick to avoid the globals' poor
>> performance
>>
>> @self function foo()
>>    x = x + 1   # expands into self[].x = self[].x + 1
>> end
>>
>> @with_self(mytype(200)) do
>>    # expands into
>>    # try
>>    #    ... save the current value of self
>>    #    global self[] = mytype(200)
>>    #    ... code
>>    # finally
>>    #    global self[] = ...restore previous value
>>    # end
>>    ...
>> end
>>
>> I used this idiom in Common Lisp all the time. It's strictly equivalent to
>> passing the object around to every function, and doesn't break the
>> "functionalness" of the code.
>>
>> Cédric
>>
>>
>> On Thursday, July 21, 2016 at 4:01:20 PM UTC-4, Marius Millea wrote:
>>>
>>> In an attempt to make some numerical code (ie something thats basically
>>> just a bunch of equations) more readable, I am trying to write a macro that
>>> lets me write the code more succinctly. The code uses parameters from some
>>> data structure, call it "mytype", so its littered with "t.a", "t.b", etc..
>>> where t::mytype. My macro basically splices in the the "t." part for me. Its
>>> kind of like how C++ member functions automatically access the class's
>>> fields, as an example. To my amazement / growing love of Julia, I actually
>>> managed to hack it together without too much difficulty, it looks like this,
>>>
>>>
>>> macro self(func)
>>>     @assert func.head == :function
>>>
>>>     # add "self" as a first function argument
>>>     insert!(func.args[1].args,2,:(self::mytype))
>>>
>>>
>>>     # recurse through AST and rename X to self.X if
>>>     # its a fieldname of mytype
>>>     function visit(ex)
>>>         if typeof(ex) == Expr
>>>             ex.args = map(visit,ex.args)
>>>         elseif (typeof(ex) == Symbol) & (ex in fieldnames(mytype))
>>>             return :(self.$ex)
>>>         end
>>>         ex
>>>     end
>>>     func.args[2] = visit(func.args[2])
>>>
>>>     show(func) # print the edited function so we can see it in action
>>>
>>>     :($(esc(func)))
>>> end
>>>
>>>
>>>
>>>
>>> Here it is in action:
>>>
>>> > @self function inc()
>>>     x = x + 1
>>> end
>>>
>>>
>>> :(function inc(self::mytype)
>>>         self.x = self.x + 1
>>>     end)
>>>
>>>
>>> inc (generic function with 1 method)
>>>
>>>
>>>
>>>
>>> > inc(mytype(0))
>>> 1
>>>
>>>
>>>
>>> where I'm assuming I've defined mytype as
>>>
>>> type mytype
>>>     x
>>> end
>>>
>>>
>>>
>>> As you can see, all it did was add self::mytype as an arg and replace x
>>> with self.x everywhere it found it. This is also super nice because there is
>>> zero run-time overhead vs. having written the "self." myself, everything
>>> happens compile time.
>>>
>>> Now for the question. I'd like to also to be able automatically pass the
>>> "self" argument to functions, so that I could write something like,
>>>
>>> @self function inc2()
>>>     inc()
>>>     inc()
>>> end
>>>
>>>
>>>
>>> and it would produce
>>>
>>> function inc2(self::mytype)
>>>     inc(self)
>>>     inc(self)
>>> end
>>>
>>>
>>>
>>> For this though, my macro needs to somehow figure out that "inc" was also
>>> defined with @self (since it shouldn't blindly add self as a first arg so
>>> other non-@self'ed function calls). Is this possible in Julia? I suppose
>>> somehow the macro must access the global scope where the expression is being
>>> evaluated? I'm not entirely sure that's doable. I'm happy to take any tips
>>> how to achieve this though, especially ones incurring minimal overhead for
>>> the rewritten function. Thanks!
>>>
>

Reply via email to