Evaluating an expression in a non-standard way


#1

Hi everyone

I have constructed an expression like follows:

quote
    for i = 1:$(Expr(:escape, Context(m)))
        $(Expr(:escape, Context(Base.println("hi"))))
    end
end

I want to evaluate this expression , but as you can see i need to evaluate “Context” parts first for which i have an eval method of my own.
then evaluate the resulting expression.

How can i do that?

Thanks


#2

When writing macros it is good practice to separate what you think should happen at compile time from what you think should happen at run time. If Context(m) takes a symbol or expression as an argument, then what you have would suffice. More likely you want Context(m) to evaluate at run time, it should appear within the quote block as if it were normal code (which it is).

I also find it much easier to just escape the entire expression if you need to escape anything at all. (I find the code hygiene transformations unbelievably confusing.) You can always create obfuscated symbols using gensym.

So, for example, you might want something like:

esc(quote
    for i ∈ 1:Context($m)
        Context(Base.println("hi"))
    end
end)

If you want both compiler information (i.e. such as variable names) and run-time information, you should either add arguments or methods to Context, or create multiple different functions. For example

somesym = Expr(:quote, s)  # some other symbol coming from the macro input somewhere, here a quote
esc(quote
    for i ∈ 1:Context($m, $somesym)
        Context(Base.println("hi"), $somesym)
    end
end)

but it’s hard for me to give better advice without knowing more about your use case.