Changing the input (i.e. x+2y) of a macro to an expression ( :(x+2y)), How to produce the same output?

Viewed 44

The code at the end of this post constructs a function which is bound to the variables of a given dictionary. Furthermore, the function is not bound to the actual name of the dictionary (as I use the Ref() statement).

An example:

julia> D = Dict(:x => 4, :y => 5)
julia> f= @mymacro4(x+2y, D)
julia> f()
14
julia> DD = D
julia> D = nothing
julia> f()
14
julia> DD[:x] = 12
julia> f()
22

Now I want to be able to construct exactly the same function when I only have access to the expression expr = :(x+2y). How do I do this? I tried several things, but was not able to find a solution.

julia> f  = @mymacro4(:(x+2y), D)
julia> f() ### the function evaluation should also yield 14. But it yields:
:(DR.x[:x] + 2 * DR.x[:y]) 

(I actually want to use it within another macro in which the dictionary is automatically created. I want to store this dictionary and the function within a struct, such that I'm able to call this function at a later point in time and manipulate the objects in the dictionary. If necessary, I may post the complete example and explain the complete problem.)

_freevars2(literal) = literal
function _freevars2(s::Symbol)
    try
        if typeof(eval(s)) <: Function
            return s
        else
            return Meta.parse("DR.x[:$s]")
        end
    catch
        return Meta.parse("DR.x[:$s]")
    end
end
function _freevars2(expr::Expr)
    for (it, s) in enumerate(expr.args)
        expr.args[it] = _freevars2(s)
    end
    return expr
end
macro mymacro4(expr, D)
    expr2 = _freevars2(expr)
    quote
        let DR = Ref($(esc(D)))
            function mysym()
                $expr2
            end
        end
    end
end
0 Answers
Related