On Thu, Jul 21, 2016 at 10:33 PM, Yichao Yu <yyc1...@gmail.com> wrote:
> On Thu, Jul 21, 2016 at 4:01 PM, Marius Millea <mariusmil...@gmail.com> > 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! > > You should not do this. It is possible to access the current module > but you don't have any scope information. > Do you mean that its possible to get the module where the expression (not the macro) is defined? If so, how do I do that? > > > >