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

Reply via email to