type
Curve*[T] = object
cp: seq[T] or iterator: T
proc linear*[T](cp: seq[T] or iterator: T): auto =
var
curve = Curve[T]()
curve.cp = cp
curve
let vf = @[0,1,2,3,4,5,6,7,8,9]
var tlin = linear(vf)
results in:
curve.nim(13, 18) template/generic instantiation of `linear` from here
curve.nim(8, 5) Error: invalid type: 'seq[int] or iterator (): int{.closure.}'
in this context: 'Curve[system.int]' for var
When I remove the seq[T] type from the proc linear*[T](cp: iterator: T) it works. When I remove the iterator linear*[T](cp: seq[T]) the error remains. What am I doing wrong here?
TIA
This gives a bit more helpful error message:
type Curve*[T] = object
cp: seq[T] or iterator: T
proc linear*[T](cp: seq[T] or iterator: T): auto =
result = Curve[T](cp: cp)
let vf = @[0,1,2,3,4,5,6,7,8,9]
var tlin = linear(vf)
/usercode/in.nim(8, 18) Error: expression 'linear(vf)' has no type (or is ambiguous)
It seems like it doesn't matter with which type you initialize cp, Curve stays the same type. An easy but inelegant solution additionally to your own solution:
type Curve*[T] = object
cp: T
proc linear*[T](cp: seq[T] or iterator: T): auto =
result = Curve[typeof cp](cp: cp)
let vf = @[0,1,2,3,4,5,6,7,8,9]
var tlin = linear(vf)
seq[int] or iterator: int is a typeclass, not a concrete type. Concrete sum types in Nim can be achieved with object variants .
type
Curve*[T] = object
case isIter: bool
of true:
cpIter: iterator: T
else:
cpSeq: seq[T]
In the end I choose a different way, maybe not the most elegant yet it works.
Curve*[T] = object
cp*: seq[T]
....
ICurve*[T] = object
cp*: iterator: T
....
func linear*[T](cp: seq[T] or iterator:T): auto =
var curve = when cp is iterator:T:
ICurve[T]()
else:
Curve[T]()
....
proc iterPoint*[T](curve: Curve[T] or ICurve[T], steps:float):auto=
#create an "internal" closure, if needed, to get the same interface for
#sequences and closure iterators as input to iterPoints.
when curve.cp is seq[T]:
func curvePoints (cps:seq[T]): auto=
return iterator(): auto=
for i in cps:
yield i
let cp = curvePoints(curve.cp)
else:
let cp = curve.cp
....
current state of the full code, a curve / spline library, is at https://ingoogni.nl/tempstuff/curve.nim.txt (needs vmath. needs pixie for the demo.)
I'll have to study the object variants, but the example kind of confused me.
Thanks
You might need to update Pixie. Older versions don't have newContext.
@ingo, thank you for using Pixie this looks great!