On Thu, Jul 21, 2016 at 11:37 PM, Cedric St-Jean <[email protected]>
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....




>
> FYI Mauro's package has something similar
> <http://parametersjl.readthedocs.io/en/latest/manual/>.
>

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