Looks like I was accidentally on 0.4, and hygiene rules changed in 0.5. This works:
using MacroTools macro withself(fdef) @assert @capture(fdef, fname_() = expr_) esc(:(@generated function $(fname)(self) expr = $(Expr(:quote, expr)) # Replace this with recursive traversal. For demo, I'm assuming a single function call @assert @capture(expr, f_(args__)) :(($f)($([arg in fieldnames(self) ? Expr(:., :self, QuoteNode(arg)) : arg for arg in args]...))) end)) end type A ii oo end a = 20 @withself foo() = ii + oo + a foo(A(33, 44)) # 97 On Friday, September 30, 2016 at 9:59:37 AM UTC-4, Cedric St-Jean wrote: > > This only works if A and type_fields are defined in the same module >> though. Although to be honest it surprised me a bit that it works at all, I >> guess the type definitions are evaluated prior to macro expansions? >> > > Good point. > > You can use a generated function then: > > using MacroTools > > macro withself(fdef) > @assert @capture(fdef, fname_() = expr_) # could accept other arguments > :(@generated function $(esc(fname))(self) > expr = $(Expr(:quote, expr)) # grab the `expr` from the macro > body > # Replace this with recursive traversal. For demo, I'm assuming a > single function call > @assert @capture(expr, f_(args__)) > :($f($([arg in fieldnames(self) ? Expr(:., :self, QuoteNode(arg)) > : arg for arg in args]...))) > end) > end > > type A > ii > oo > end > > a = 20 > @withself foo() = ii + oo + a > > foo(A(33, 44)) # 97 > > Since generated functions are passed the _type_ of their arguments, which > is what you were looking for. It's an abuse of Julia's metaprogramming > facilities in strict Lisp tradition ;) > > On Friday, September 30, 2016 at 5:32:49 AM UTC-4, Marius Millea wrote: > >> >> Would eval'ing the type inside the macro work? This shows [:x, :y] >>> >>> >> This only works if A and type_fields are defined in the same module >> though. Although to be honest it surprised me a bit that it works at all, I >> guess the type definitions are evaluated prior to macro expansions? >> >> >> A macro which defines a type-specific version @self_MyType of your @self >>> macro at the definition of the type: >> >> >> Yea, the solutions both me and fcard coded up originally involved having >> to call a macro on the type definition, this is precisely what I'm trying >> to get rid of right now. The reason for not using @unpack is just that its >> more verbose than this solution (at the price of the type redefinition >> thing, but for me its a fine tradeoff). It *really* like getting to write >> super concise functions which read just like the math they represent, >> nothing extra distracting, e.g. from my actual code: >> >> """Hubble constant at redshift z""" >> @self Params Hubble(z) = Hfac*sqrt(ρx_over_ωx*((ωc+ωb)*(1+z)^3 + ωk*(1+z >> )^2 + ωΛ) + ργ(z) + ρν(z)) >> >> >> """Optical depth between two redshifts given a free electron fraction >> history Xe""" >> @self Params function τ(Xe::Function, z1, z2) >> σT*(ωb*ρx_over_ωx)/mH*(1-Yp) * quad(z->Xe(z)/Hubble(z)*(1+z)^2, z1, >> z2) >> end >> >> >> >> >> >> >> >> >>