macros - 如何评估 nim 中的表达式?
问题描述
我正在尝试eval
在 nim 中执行与 Python 中的方法等效的方法。我的印象是parseStmt
从macros
包中应该可以帮助我解决这个问题,但我面临一个我不明白的编译问题。
import macros
echo parseStmt("1 + 2")
我本来希望这会3
在执行时打印出来,但编译却抱怨说
Error: request to generate code for .compileTime proc: $
我找到了这个线程,并且那里的示例有效,并且在此之后,我能够使以下程序按预期工作:
import macros
import strformat
macro eval(value: string): untyped =
result = parseStmt fmt"{value}"
echo eval("1+2")
但我根本不明白为什么它需要以这种方式编写。如果我内联语句, let value = "1 + 2"; echo parseStmt fmt"{value}"
,我会得到与上面相同的编译错误。
另外,在上述宏的上下文中,为什么与 ,parseStmt value
不同?parseStmt fmt"{value}"
eval
我在这里想念什么?
提前感谢您的任何澄清!
解决方案
与作为解释型语言的 Python 不同,Nim 是经过编译的。这意味着所有代码都在编译时被解析并转换为机器代码,而您最终得到的程序对 Nim 完全不了解(至少只要您不将 Nim 编译器作为模块,这是可能的)。因此parseStmt
,Nim 中的所有宏/模板扩展内容都是在编译期间完全完成的。该错误虽然可能有点难以阅读,但它试图告诉您传递给的内容$
(这是 Nim 中的转换为字符串的运算符,并由echo
其所有参数调用)是编译时的东西,可以'不能在运行时使用。在这种情况下,因为parseStmt
不返回"3"
,它返回类似的东西NimNode(kind: nnkIntLit, intVal: 3)
,并且NimNode
type 仅在编译时可用。然而,Nim 允许您在编译时运行代码以返回其他代码,这就是宏的作用。eval
您在那里编写的宏采用value
在运行时解析为字符串的任何语句,作为NimNode
. 这也是为什么result = parseStmt value
在您的情况下不起作用的原因,因为它还value
不是字符串,但可能类似于从标准输入中读取字符串,这会在运行时生成字符串。然而,strformat
这里的使用有点令人困惑和矫枉过正。如果您将代码更改为:
import macros
macro eval(value: static[string]): untyped =
result = parseStmt value
echo eval("1+2")
它会工作得很好。这是因为我们现在已经告诉 Nimvalue
需要static
在编译时知道 ie。在这种情况下,字符串文字"1+2"
在编译时显然是已知的,但这也可能是对编译时过程的调用,或者甚至是staticRead
在编译期间读取文件的输出。
如您所见,Nim 非常强大,但编译时和运行时之间的界限有时会有点令人困惑。另请注意,您的eval
过程实际上并未在编译时评估任何内容,它只是返回 Nim 代码1 + 2
,因此您的代码最终为echo 1 + 2
. 如果您想在编译时实际运行代码,您可能需要查看编译时过程。
希望这有助于阐明您的问题。
推荐阅读
- r - 谷歌地球引擎中的图像统计数据和 R 中的 rgee 包?
- splash-screen - pubspec.yaml 中的闪屏引发错误依赖项可能只有一个源
- google-sheets - 为什么在 Google 时间表上的持续时间总和总是返回零
- ruby - 如何使用 url 共享私有 S3 对象?
- ansible - 如何在 Anible 中访问字典中的列表?
- html - CSS溢出-y滚动条超出div
- neo4j - 根据 Neo4j 中所有节点中该属性的最大值设置属性值
- c# - c# .net core 读取 appsettings.json 与 ConfigurationBuilder 类性能问题
- node.js - 我正在尝试将多个图像上传到 multer diskstorage,但我似乎已经尝试了一切,但我仍然得到了意想不到的领域
- pine-script - Pinescript TradingView 回测策略不产生任何数据