Ben*_*ren 4 macros metaprogramming nim-lang
我正在尝试eval在 nim 中执行与Python 中的方法等效的方法。我的印象是parseStmt从macros包中应该可以帮助我解决这个问题,但我正面临一个我不明白的编译问题。
import macros
echo parseStmt("1 + 2")
Run Code Online (Sandbox Code Playgroud)
我本来希望它3在执行时打印出来,但编译却抱怨说
Error: request to generate code for .compileTime proc: $
Run Code Online (Sandbox Code Playgroud)
我找到了这个线程,那里的例子有效,在此之后,我能够使以下程序按我的预期工作:
import macros
import strformat
macro eval(value: string): untyped =
result = parseStmt fmt"{value}"
echo eval("1+2")
Run Code Online (Sandbox Code Playgroud)
但我完全不明白为什么它需要以这种方式编写。如果我内联语句, let value = "1 + 2"; echo parseStmt fmt"{value}",我会得到与上面相同的编译错误。
另外,为什么parseStmt value与parseStmt fmt"{value}", 在上述eval宏的上下文中不同?
我在这里缺少什么?
预先感谢您的任何澄清!
PMu*_*nch 10
与作为解释型语言的 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")
Run Code Online (Sandbox Code Playgroud)
它会工作得很好。这是因为我们现在告诉 Nimvalue需要static在编译时知道 ie。在这种情况下,字符串文字"1+2"在编译时显然是已知的,但这也可能是对编译时过程的调用,甚至是staticRead在编译期间读取文件的输出。
正如您所看到的,Nim 非常强大,但是编译时和运行时之间的障碍有时会令人困惑。另请注意,您的eval过程实际上并不在编译时评估任何内容,它只是返回 Nim 代码,1 + 2因此您的代码最终是echo 1 + 2. 如果您想在编译时实际运行代码,您可能需要查看编译时过程。
希望这有助于阐明您的问题。