Is there a native/elegant way to convert seq into tuple?
For example, I'd like to instantiate some variables basing on values stored in a seq like this:
var s: seq[int] = @[1,2,3]
var (a,b,c) = s
Possible solution would look like this (or even more elegant?):
iterator values* [T] (s: seq[T]): T =
var i = 0
while i <= high(s):
yield i
inc i
var s: seq[int] = @[1,2,3]
var (a,b,c) = (s.values) #doesn't work since values() is not treated as iterator
proc fillTuple[T: tuple, V](target: var T, input: openarray[V]) =
var index = 0
for field in target.fields:
assert input.len > index
field = input[index]
inc(index)
var myTuple: tuple[a,b,c: int]
fillTuple(myTuple, @[1, 2, 3])
Or, if you want the tuple as return value:
proc fillTuple[T: tuple, V](input: openarray[V]): T =
var index = 0
for field in result.fields:
assert input.len > index
field = input[index]
inc(index)
var myTuple = fillTuple[tuple[a,b,c:int], int](@[1, 2, 3])
Thanks Flyx, your solution solves the task, but still unlikely able to generate (target) tuple of arbitrary size: for example, how would you write code to convert seq/array which consists out of 100 (or 1000 or 10M elements) ? You would have to write something like:
var myTuple: tuple[a00,a01,a02,a03,a05 ... a98,a99: int]
fillTuple(myTuple, input_seq)
I hope I'm wrong and there is an elegant way to define a large tuple.
Does Nim able to construct/initialize tuple using an iterator/generator ?
The compiler needs to know the size of the tuple in compile time. I can imagine a code such that the following works:
var myTuple = fillTuple(5, @[1, 2, 3, 4, 5])
where 5 is known at compile time (it can be a const).I hope I'm wrong and there is an elegant way to define a large tuple.
What do you need a tuple this size for? Your problem is likely that you use the wrong tool for the job. The need to write
var myTuple: tuple[a00,a01,a02,a03,a05 ... a98,a99: int]
roots from the nature of the tuple type. If you do not want to do that, you likely do not want to use a tuple.
Inside fillTuple() if I add assert input.len == result.fields.len, I get
Error: attempting to call undeclared routine: 'fields'
I guess that's because it's an iterator. So I try
import sequtils
assert input.len == sequtils.toSeq(result.fields).len
and I get
Error: type mismatch: got (seq[RootObj], int)
How do I get the number of fields in the result tuple?