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! >>> >