Reputation: 26710
TL;DR: If you have a similar problem, check first that you haven't done something completely stupid like confusing a :
with a =
. I was so baffled by the error message that I managed to reproduce a stupid mistake by yet another stupid mistake, so have a good laugh:
I came upon a problem where I was struggling with the error no generic parameters allowed
. The problem is probably best explained in a simplified from: The problem of comparing a tuple only by its first element. Consider this example:
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)
This example produces Error: no generic parameters allowed for sort
. I have tried all kinds of syntactic variations, also defining the comparator proc nested. What I do not understand: Why is the comparator still considered generic? I was expecting that within sortByFirstTupleElement
the types K
and V
are instantiated types from the calling context, i.e, int
and NotComparable
. Therefore I expected cmpByKey[K,V]
to be the concrete cmpByKey[int,NotComparable]
. Is there a syntactic trick to make the comparator concrete?
If this is not possible, what are the possible workarounds here? Maybe not just specifically in this example, but in general? I guess this problem arises every time a generic proc has to pass on another proc which involves the generic type?
Upvotes: 1
Views: 601
Reputation: 8730
Your problem is that you're calling sort
with the wrong parameters. You don't pass the data
parameter to sort, and data
is not a var parameter, so it isn't mutable. Also, cmp
is not a named parameter, so just pass the comparison function directly. E.g.:
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)
Also, the let compare = ...
is superfluous. You can call data.sort(cmpByKey[K,V])
directly.
You get the error message because you're using the object constructor syntax (cmp: compare
) rather than the named parameter syntax (cmp = compare
), which makes Nim look for an object type called sort
rather than a procedure called sort
. The error message is still a bit confusing, but that's where it's coming from.
Upvotes: 4