我正在尝试编写一个评估表达式然后将其与一些值进行比较的宏。对于这篇文章,我已将问题简化为一个较小的示例。
macro small_bad(item)
quote
$(use_val(esc(item)))
end
end
function use_val(val)
quote
if $val == 1
1
elseif $val == 2
2
else
-1
end
end
end
因为我不想多次评估 expr,所以我想将它保存在一个变量中。所以我尝试了这个:
macro small_good(item)
quote
begin
val = $(esc(item))
$(begin
use_val(val)
end)
end
end
end
但是后来我val
在@small_good
.
我也尝试过传递use_val(:val)
,但这也失败了,因为宏系统将重命名
val
为其他名称。
我怎样才能做到这一点?
编辑: 给定第一个答案,我在实际代码中尝试了这个
macro match(item, arms)
var = gensym(:var)
quote
let $var = $(esc(item))
$(begin
code = :nothing
for e in reverse(filter((e) -> e isa Expr, arms.args))
code = make_match(var, e, code)
end
code
end)
end
end
end
并得到UndefVarError: ##var#253 not defined
免责声明:我知道@match
宏已经在 Match.jl 包中实现,我正在重新实现它的一个子集作为学习练习
编辑2:
我想到了。在使用了 François Févotte 的建议后,我现在不得不更改我的真实版本,use_val
而$(esc(val))
不是$val
.
我的错误是没有包括那个细节。将更新要点以反映这一点