我想知道是否可以定义一个只有当值是特定类型时才能修改表达式值的宏?
这是一个最小的例子:
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
但是虽然这样做有点不对劲,但我可能做错了或试图做出太多的事情......
答案 0 :(得分:3)
不,你应该从不尝试检查宏内的类型或值。使用eval
来确定宏中某些东西的类型或值可能会在非常有限的情况下起作用,但它几乎可以在每个实际使用中中断。相反,只需让宏插入一个泛型函数的调用 - 这就是Julia擅长挑选分离类型(作为方法调度)和值(在方法中)的地方:
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