2017-02-03 2 views
2

Мне интересно, можно ли определить макрос, который может изменять значения выражения только в том случае, если значения имеют определенный тип?Доступ к значениям в выражении с использованием макроса

Вот минимальный пример:

type Special 
    x::Int 
end 

f1(s, n::Special) = println("f1", s, n) 
f2(s, n::Special) = println("f2", s, n) 

x1 = Special(3) 
x2 = Special(5) 

expr = :(
    f1("this is f1", x1), 
    f2("this is f2", x2) 
    ) 

Теперь макрос может быть в состоянии исследовать значение аргументов функции, определить, что x1 и x2 имеет типа Special, запустить какую-либо функцию для изменения их значения, скажем, путем изменения от 3 до 4 и от 5 до 2 (это может включать сравнение двух значений), затем передать выражение обратно вызывающему. Окончательный результат будет эквивалентен вызову:

f1("this is f1", 4) 
f2("this is f2", 2) 

я обнаружил, что можно получить доступ к значениям в макросе с помощью:

eval(eval(filter(x -> typeof(eval(x)) == Special, expr.args[1].args))[1]).x 

=> 3 

но, несмотря на это работает, он выглядит не так, и я мощь либо делать это неправильно или пытаться сделать что-то слишком ...

ответ

3

Нет, вы должны never попытаться проверить типы или значения внутри макросов. Использование eval для определения типа или значения чего-либо в макрокоманде может работать в очень ограниченных ситуациях, но оно будет ломаться почти во всех реальных целях. Вместо этого, просто макросоци- вставить вызов функции общего - вот где Джулия выделяется на собирание, кроме типов (как метод отправки) и значения (в пределах метода):

munge_special(x::Special) = Special(x.x + 42) 
munge_special(x) = x 
macro do_something_special(x) 
    return :(munge_special($(esc(x)))) 
end 

julia> @do_something_special Special(2) 
Special(44) 

julia> @do_something_special 3 
3 
+0

Спасибо Мт. Я пересматриваю свой подход ... :) – daycaster

Смежные вопросы