首页 > 解决方案 > 如何评估 nim 中的表达式?

问题描述

我正在尝试eval在 nim 中执行与 Python 中的方法等效的方法。我的印象是parseStmtmacros包中应该可以帮助我解决这个问题,但我面临一个我不明白的编译问题。

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

我在这里想念什么?

提前感谢您的任何澄清!

标签: macrosmetaprogrammingnim-lang

解决方案


与作为解释型语言的 Python 不同,Nim 是经过编译的。这意味着所有代码都在编译时被解析并转换为机器代码,而您最终得到的程序对 Nim 完全不了解(至少只要您不将 Nim 编译器作为模块,这是可能的)。因此parseStmt,Nim 中的所有宏/模板扩展内容都是在编译期间完全完成的。该错误虽然可能有点难以阅读,但它试图告诉您传递给的内容$(这是 Nim 中的转换为字符串的运算符,并由echo其所有参数调用)是编译时的东西,可以'不能在运行时使用。在这种情况下,因为parseStmt不返回"3",它返回类似的东西NimNode(kind: nnkIntLit, intVal: 3),并且NimNodetype 仅在编译时可用。然而,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. 如果您想在编译时实际运行代码,您可能需要查看编译时过程。

希望这有助于阐明您的问题。


推荐阅读