Referencing a module on RHS of expression while Metaprogramming


#1

Hi all,

So using meta-programming, I can define a new function customsum in a slightly round-about way using interpolation as follows:

fn = :sum
@eval $(Symbol("custom$(fn)"))(x::Vector{<:Number}) = Base.sum(x)

But now, I also want to interpolate onto the RHS of the expression, and include the module name reference (because my actual problem is more complicated than this MWE). I thought the following would work:

@eval $(Symbol("custom$(fn)"))(x::Vector{<:Number}) = $(Symbol("Base.$(fn)"))(x)

but it does not. Calling customsum results in ERROR: UndefVarError: Base.sum not defined.

I’ve been banging my head against the wall on this for an hour now trying to work out the right syntax, but am admitting defeat and posting here. Any help would be most greatly appreciated.

Cheers,

Colin


#2

Base.sum is not a symbol; it’s an expression (it’s the . operator acting on :Base and :sum). You can show this with dump():

julia> dump(:(Base.sum))
Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol Base
    2: QuoteNode
      value: Symbol sum
  typ: Any

And you can construct that expression in the same way:

julia> Expr(:., :Base, QuoteNode(:sum))
:(Base.sum)

julia> eval(Expr(:., :Base, QuoteNode(:sum)))
sum (generic function with 17 methods)

#3

Argh! Yes, I see it now. So I could do:

@eval $(Symbol("custom$(fn)"))(x::Vector{<:Number}) = eval(Expr(:., :Base, QuoteNode(:sum)))(x)

or, much more simply:

@eval $(Symbol("custom$(fn)"))(x::Vector{<:Number}) = Base.$(Symbol("$(fn)"))(x)

Thanks so much, that was a huge help.

Cheers,

Colin