Nim:Return Table 来自程序

Nim: Return Table from Procedure

我一直在尝试在 Nim 中编写一个简单的词法分析器,我需要将我的过程 return 变成 Table。我在实现这一点时遇到了一些问题,这是我的代码:

main.nim

# Code

import lexer

echo lexer.lex("hi")

lexer.nim

import tables

proc lex*(code: string): Table = 
    let variable = to_table({"1": "hi"})

    return variable

每次我尝试编译代码 (nim c -r --outDir:"../bin" "main.nim") 时,我都会收到以下错误:

/path/to/main.nim(5, 15) template/generic instantiation of `lex` from here
/path/to/lexer.nim(3, 26) Error: cannot instantiate 'Table[A, B]' inside of type definition: 'lex'; Maybe generic arguments are missing?

我可能犯了一些简单的错误,但我在这上面浪费了太多时间,所以非常感谢您的帮助。

操作系统:Solus

Nim 版本: 1.2.0

代码有几个问题,但让我们开始尝试破译编译器错误:Table[A, B]' inside of type definition: 'lex';可能缺少通用参数?.

Nim 有类型推断,但可以说它是 前向声明的 并且在第一时间失败是未知的。在这种情况下,编译器正在检查您的 main.nim 文件并发现您想要调用具有以下签名的过程:

proc lex*(code: string): Table

它看到的是 all,并且由于 Tablea generic type,它无法实例化 return 类型,因为它没有仅基于 proc 签名,不知道泛型类型 AB 应该是什么。这就是编译器所抱怨的。您可能会争辩说,编译器可以尝试查看 proc 并找出通用签名的特定类型,但这需要编译器的一部分做更多的工作,并且会减慢编译时间,这是 Nim 社区非常关心的一个指标。

有两种方法可以解决这个问题,一种是简单的方法,即在 proc 签名中声明类型,另一种是困难的方法,它需要您在调用者处指定类型。前者是将proc签名更改为:

proc lex*(code: string): Table[string, string]

后一种是在调用方指定类型,这意味着将您的 main.nim 代码更改为:

echo lexer.lex[Table[string, string]]("hi")

不幸的是,第二个解决方案也不会编译,因为 main.nim 模块现在没有关于 Table 类型的任何信息:错误:未声明的标识符:'Table'。为了继续使用此解决方案,您需要从 lexer.nim 导出 Table 类型并添加 an export statement to that module,或者在 main.nim 中导入 tables 模块(以及任何其他未来的调用模块)。

您需要在 proc 编辑的 return 类型中明确。正如 Grzegorz 所说,更改为:

proc lex*(code: string): Table[string, string] =

够了。无需修改 main.nim 代码中的任何内容。

需要考虑两件小事:

  1. Nim procs 已经用 return 类型初始化了一个 result 变量,它是隐式 returned,所以你的 proc 可以重写如:

    proc lex*(code: string): Table[string, string] =
      result["1"] = "hi"
    
  2. 不需要命名空间 lex proc in main, 除非有名称冲突:

    import lexer
    
    lex("hi")