如何解决"no generic parameters allowed"

How to solve "no generic parameters allowed"

TL;DR: 如果您有类似的问题,请先检查您是否没有做过完全愚蠢的事情,例如混淆 :=。我对错误消息感到非常困惑,以至于我设法用另一个愚蠢的错误重现了一个愚蠢的错误,所以好好笑一下:

我遇到了一个问题,我正在努力解决错误 no generic parameters allowed。这个问题可能最好用一个简化的方式来解释:The problem of comparing a tuple only by its first element。考虑这个例子:

import algorithm

# just a dummy type emphasizing that it should not be
# used for the comparison
type
  NotComparable = object

# generic proc to compare a tuple by the first element
proc cmpByKey[K,V](x: (K,V), y: (K,V)): int = 
  system.cmp(x[0], y[0])

# now the actual challenge: how to write a function which
# takes some collection of tuples and defines a local
# key comparator for the given tuple.
proc sortByFirstTupleElement[K,V](data: seq[(K,V)]) =
  let compare = cmpByKey[K,V]
  sort[(K,V)](cmp: compare)

let data = @[(2, NotComparable()),
             (1, NotComparable()),
             (3, NotComparable())]

sortByFirstTupleElement[int, NotComparable](data)

此示例生成 Error: no generic parameters allowed for sort。我尝试了各种语法变体,还定义了嵌套的比较器过程。我不明白的是:为什么比较器仍然被认为是通用的?我期望在 sortByFirstTupleElement 中,类型 KV 是来自调用上下文的实例化类型,即 intNotComparable。因此我希望 cmpByKey[K,V] 成为具体的 cmpByKey[int,NotComparable]。是否有句法技巧可以使比较器具体化?

如果这不可能,这里有哪些可能的解决方法?也许不仅仅是在这个例子中,而是在一般情况下?我想每次泛型过程必须传递另一个涉及泛型类型的过程时都会出现这个问题?

您的问题是您使用错误的参数调用 sort。您不传递 data 参数进行排序,并且 data 不是 var 参数,因此它不是可变的。另外,cmp 不是命名参数,所以直接传递比较函数即可。例如:

import algorithm

# just a dummy type emphasizing that it should not be
# used for the comparison
type
  NotComparable = object

# generic proc to compare a tuple by the first element
proc cmpByKey[K,V](x: (K,V), y: (K,V)): int = 
  system.cmp(x[0], y[0])

# now the actual challenge: how to write a function which
# takes some collection of tuples and defines a local
# key comparator for the given tuple.
proc sortByFirstTupleElement[K,V](data: var seq[(K,V)]) =
  let compare = cmpByKey[K,V]
  data.sort(compare)

var data = @[(2, NotComparable()),
             (1, NotComparable()),
             (3, NotComparable())]

sortByFirstTupleElement(data)

此外,let compare = ... 是多余的。可以直接调用data.sort(cmpByKey[K,V])

您收到错误消息是因为您使用的是对象构造函数语法 (cmp: compare) 而不是命名参数语法 (cmp = compare),这使得 Nim 查找名为 sort 而不是名为 sort 的过程。错误消息仍然有点令人困惑,但这就是它的来源。