# file: main.nim
import sequtils
import tables
# this import messes up the functionality of table iterators
import b
let t = initOrderedTable[int, int]()
let s = toSeq(keys(t))
echo s
# file: b.nim
type
Data*[T] = object
data*: seq[T]
proc toSeq*[T](c: Data[T]): seq[T] =
c.data
Compiling main.nim results in: Error: attempting to call undeclared routine: 'keys'. Basically none of the iterators from tables can be used in a toSeq context when another module (accidentally) exports an overload of toSeq.
That's because overloaded procs need to have the same untyped parameters in the same positions. Documented limitation. sequtils.toSeq always works then. Don't "accidentically export" a toSeq.
Having a toSeq function is the natural choice for any data structure which support "to seq conversion", so this is a rather nasty pitfall. In fact I have been using toSeq functions in several projects of mine and I always though toSeq + iterator visibility is just broken in general because I never could do something like toSeq(key(t)) anywhere. It was only by chance to find the cause...
Wouldn't it be possible to solve the issue by avoiding an untyped implementation of toSeq in sequtils and explicitly implement it for iterators and sized collections (maybe by introducing a concept).
Also I struggle to find the documented limitation and I still can't make sense of the error message here. Apparently the overloading resolution seems to pick the right version of toSeq here, otherwise I would expect a different error. But why does the compiler complain with attempting to call an "undeclared" routine, which obviously is declared?
Wouldn't it be possible to solve the issue by avoiding an untyped implementation of toSeq in sequtils and explicitly implement it for iterators and sized collections (maybe by introducing a concept).
Certainly.
Apparently the overloading resolution seems to pick the right version of toSeq here, otherwise I would expect a different error. But why does the compiler complain with attempting to call an "undeclared" routine, which obviously is declared?
Because it doesn't pick up the right overload.
Certainly.
Then we should probably go for a typed solution in the stdlib to avoid the issue. If you don't mind I'll reopen...
Edit: Oh haha, I cannot re-open :).
In fact even the standard library violates the "don't accidentally export a toSeq" for instance in nre, i.e. this also fails to compile:
import sequtils, tables, nre
let t = initOrderedTable[int, int]()
let s = toSeq(keys(t))
I'm afraid the (current?) limitations of inline iterators make a proper solution very tough :-(.
In fact even the standard library violates the "don't accidentally export a toSeq" for instance in nre, i.e. this also fails to compile
I know.
just hit this bug again; import nre messes up toSeq.
Wouldn't it be possible to solve the issue by avoiding an untyped implementation of toSeq in sequtils and explicitly implement it for iterators and sized collections (maybe by introducing a concept).
Certainly.
no, unfortunately with the way iterators are implemented in the compiler today, I don't think it's possible to have a toSeq(a: typed).
See also https://github.com/nim-lang/Nim/issues/9219
I don't think it's possible to have a toSeq(a: typed)
I think the proposal is to have various overloads of toSeq - one for iterators and the other ones for specific collections. As far as I can tell, this should work, at the cost of some repetition
This issue has been automatically marked as stale because it has not had recent activity. If you think it is still a valid issue, write a comment below; otherwise it will be closed. Thank you for your contributions.
Most helpful comment
In fact even the standard library violates the "don't accidentally export a
toSeq" for instance in nre, i.e. this also fails to compile:I'm afraid the (current?) limitations of inline iterators make a proper solution very tough :-(.