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