Изменение ввода (т. Е. X + 2y) макроса в выражение (: (x + 2y)). Как создать такой же вывод? - PullRequest
2 голосов
/ 22 марта 2020

Код в конце этого поста создает функцию, которая связана с переменными данного словаря. Кроме того, функция не привязана к фактическому имени словаря (как я использую оператор Ref ()).

Пример:

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

Теперь я хочу иметь возможность построить точно такую ​​же функцию, когда у меня есть доступ только к выражению expr = :(x+2y). Как мне это сделать? Я попробовал несколько вещей, но не смог найти решение.

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

(Я действительно хочу использовать его в другом макросе, в котором словарь создается автоматически. Я хочу сохранить этот словарь и функцию внутри структуры, так что я могу вызывать эту функцию позднее и манипулировать объектами в словаре. При необходимости я могу опубликовать полный пример и объяснить полную проблему.)

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