Nim return 包含 proc 的自定义元组

Nim return custom tuple containing proc

我正在尝试创建一个 returns 自定义元组的过程,其中包含一个 proc 类型的元素,即

type
  CustomTuple = tuple
    foo: proc(input: int): int

proc createCustomTuple(): CustomTuple =
  (foo: proc(input: int): int = 10)

但是,当我编译它时出现以下错误(我在 Windows 上使用 Nim 版本 1.2.6 进行编译)。

Error: type mismatch: got <tuple[foo: proc (input: int): int{.noSideEffect, gcsafe, locks: 0.}]> but expected 'CustomTuple = tuple[foo: proc (input: int): int{.closure.}]'

所以编译器认为我返回的是常规元组而不是 CustomTuple 但我不知道如何更改它以使其工作。 Nim manual 中的元组文档显示自定义元组以我正在做的方式构建,我找不到任何从 proc 返回自定义元组的示例。

如果我将我的 CustomTuple 定义更改为包含非 proc 的类型,那么它会成功编译,因此它似乎与我的自定义元组有关,该元组包含导致此编译失败的 proc。

谁能解释一下为什么上面的代码不能编译?

type
  CustomObject = object
    foo: proc(input: int): int

proc createCustomObject(): CustomObject =
  #(foo: proc(input: int): int = 10)
  #result.foo = proc(input: int): int = 10
  CustomObject(foo: proc(input: int): int = input * 2)

var x = createCustomObject()
echo x.foo(2)

我认为我的原始代码不起作用的原因是 Nim 在将 proc 添加到元组时无法自动将其转换为闭包。 There is some discussion around this in the Nim forums.

由于 proc 未转换为闭包,编译器无法确定返回的元组是 CustomTuple,因为类型不匹配,这解释了错误消息。

因此,当将 proc 打包在元组中时,您需要将其显式转换为闭包。这可以通过像这样显式地转换过程来完成:

type
  CustomTuple = tuple
    foo: proc(input: int): int

proc createCustomTuple(): CustomTuple =
  (foo: (proc(input:int):int)(proc(input: int): int = 10))

或者通过添加这样的 {.closure.} pragma(我认为这样更干净)。

type
  CustomTuple = tuple
    foo: proc(input: int): int

proc createCustomTuple(): CustomTuple =
  (foo: proc(input: int): int {.closure.} = 10)

如果您不想执行其中任何一个,您可以根据 Salewski 的回答将过程分配给隐式 result 变量的 foo 属性。

这也解释了为什么 Salewski 将 proc 分配给隐式 result 变量的 foo 属性 的原始解决方案有效;在这种情况下,编译器能够自动将 proc 转换为闭包。