macros - Julia:宏、表达式和 Meta.parse
问题描述
以下所有这些代码行都是 Julia 表达式:
x = 10
1 + 1
println("hi")
如果你想将表达式传递给宏,它的工作原理是这样的。宏 foo 只返回给定的表达式,它将被执行:
macro foo(ex)
return ex
end
@foo println("yes") # prints yes
x = @foo 1+1
println(x) # prints 2
如果要将字符串转换为表达式,可以使用 Meta.parse():
string = "1+1"
expr = Meta.parse(string)
x = @foo expr
println(x) # prints 1 + 1
但是,很明显,宏将 expr 视为一个符号。我在这里做错了什么?
提前致谢!
解决方案
宏hygiene
很重要“宏必须确保它们在返回的表达式中引入的变量不会意外地与它们扩展的周围代码中的现有变量发生冲突。” 文档中有一个部分。最简单的就是展示一个简单的案例:
macro foo(x)
return :($x)
end
当你在 REPL 中输入一个普通表达式时,它会立即被计算。要抑制该评估,请将表达式用. 括起来:( )
。
julia> 1 + 1
2
julia> :(1 + 1)
:(1 + 1)
# note this is the same result as you get using Meta.parse
julia> Meta.parse("1 + 1")
:(1 + 1)
因此,Meta.parse
将适当的字符串转换为表达式。如果你eval
得到结果,表达式将被评估。请注意,打印一个简单的表达式会删除外部:( )
julia> expr = Meta.parse("1 + 1")
:(1 + 1)
julia> print(expr)
1 + 1
julia> result = eval(expr)
2
通常,宏用于在对表达式进行通常的评估之前进行操作;它们主要是语法转换。在编译/评估/执行其他源代码之前执行宏。
而不是寻找一个评估字符串的宏,就好像它是直接输入到 REPL(不带引号)中一样,而是使用这个函数。
evalstr(x::AbstractString) = eval(Meta.parse(x))
虽然我不推荐下一个宏,但了解该技术是件好事。一个名为的宏<name>_str
是这样使用的<name>"<string contents>"
:
julia> macro eval_str(x)
:(eval(Meta.parse($x)))
end
julia> eval"1 + 1"
2
(ps不要重用Base函数名作为变量名,str
不要使用string
)
如果有什么我没有解决的,请告诉我。
推荐阅读
- jquery - 两个不同页面上的两个元素可以在 HTML/CSS 中具有相同的 ID 吗?
- python - fashion_mnist.load_data() 无法强制远程关闭连接
- python - 我应该如何使用我所有的 cpu 功率有效地在 python 中加载文件?
- android - org.gradle.api.resources.ResourceException:无法在 Android Studio 3.2 中获取资源
- jquery - AJAX 之后的引导表样式
- java - 如何使用 Firebase 中的图像和文本填充列表视图?
- django - Wagtail:如何拥有多种类型的管理员
- python - 如何使用 python 查找并连接所有可用的 wifi 信号?
- pygame - 如何在pygame中绘制透明矩形
- types - 如何创建 llvm 类型