尼姆:"invalid type ... in this context" 错误

Nim: "invalid type ... in this context" error

我正在尝试将 Nim 与 Elm 一起使用。 Elm 有一个端口系统,可以发送和接收消息,类似于 web worker。

我在主模块中有这段代码:

import ./elm
import ./portMessages


type
    State = object
        elmProgram: elm.Program
        portToElm: elm.SubPort[portMessages.Outgoing]


# Error is with this function
proc newState(
    elmProgram: elm.Program,
): State =
    return State(
        elmProgram: elmProgram,
        portToElm: elmProgram.getSubPort("rawSubscribe"),
    )

当我尝试编译时,我从编译器收到此错误消息:

Error: invalid type: 'SubPort[SubPort.T]' in this context: 'proc (elmProgram: Program): State' for proc

这是 elm 模块。 SubPort 类型允许 T 通过端口发送。

type
    Program* {.importjs.} = ref object of JsRoot
    SubPort*[T: JsRoot] {.importjs.} = ref object of JsRoot


# Get a reference to a Sub port (to Elm)
proc getSubPort*[T: JsRoot](
    program: Program,
    name: cstring,
): SubPort[T] {.importjs: "#.ports[#]".}

这是 'portMessages' 模块:

type
    OutgoingKind* {.importjs.} = enum
        portErrorPopup = 0,
    
    Outgoing* {.importjs.} = ref object of JsRoot
        case kind*: OutgoingKind
        of portErrorPopup:
            msg*: cstring

类型不匹配是因为 getSubPort("messages") 仍然是未指定的泛型,因为它的返回类型是 SubPort[T],无法从其参数中推断出来。

同时,您已指定 State 类型的成员 portToElm 具有 SubPort[Outgoing]

类型

答案应该很简单:

proc newState(elmProgram: Program): State =
    State(
        elmProgram: elmProgram,
        portToElm: getSubPort[Outgoing](elmProgram,"rawSubscribe")
    )

但是由于编译器错误,这仍然不起作用。解决方法是使用通用限制的概念:

elm中:

type
  Program* {.importjs.} = ref object of JsRoot
  IsJsRoot = concept type t
    t is JsRoot
  SubPort*[T: IsJsRoot] {.importjs.} = ref object of JsRoot

proc getSubPort*[T:IsJsRoot](
    program: Program, name: cstring): SubPort[T]{.importjs: "#.ports[#]".}

(我不明白为什么 SubPort 首先需要通用,尤其是因为它是 importjs,但这不是重点)

SubPort 类型的定义中删除 : JsRoot

type
    # ...
    SubPort*[T] {.importjs.} = ref object of JsRoot

调用getSubPort时也需要指定portMessages.Outgoing:

return State(
    # ...
    portToElm: elmProgram.getSubPort[: portMessages.Outgoing]("rawSubscribe"),
)