-
Notifications
You must be signed in to change notification settings - Fork 23
Description
A lot of APIs could benefit from the new iterable type (which accepts called iterators), but right now there's still 1 issue: iterable[T] only accepts called iterators, not values (eg seq[T]).
This proposal would allow a value a with items(a) defined on it to match against iterable[T], in the same way that for implicitly adds items:
template fn(a: iterable[T]) = discard
template iota(n: int): int = for i in 0..<n: yield i
fn(iota(3)) # ok
fn(items(@[0, 1, 2]) # ok
fn(@[0, 1, 2]) # before RFC: CT error; with RFC: transformed into fn(items(@[0, 1, 2]))the implicit conversion would have lower priority than an explicit overload, eg:
template fn(a: iterable[T]): int = 1
template fn[T](a: T): int = 2
assert fn(iota(3)) == 1
assert fn(@[0,1,2]) == 2
# ditto if we had: `template fn[T](a: seq[T]): int = 2` etcexplicit overloads are still useful in cases where you need extra information from the type, eg a len; but in many cases, the iteration is all you need and an overload doesn't add value
benefits
avoids having to add need-less boilerplate that would require adding overloads for both iterable[T] and Iterable[T] where the latter is defined below:
before RFC: requires boilerplate of adding template bar(a: Iterable[int]): untyped = bar(items(a))
when true:
type Foo = object
iterator mitems(a: Foo): int = discard
iterator items(a: Foo): int = discard
template bar(a: iterable[int]) = echo "in bar"
type Iterable[T] = concept x
items(x) is T
template bar(a: Iterable[int]): untyped = bar(items(a))
# template bar(a: Iterable[int] | iterable[int]) = # doesn't work, and probably a bad idea to conflate typed and iterable
var x: Foo
bar(x.items)
bar(x.mitems)
bar(x)after RFC:
when true:
type Foo = object
iterator mitems(a: Foo): int = discard # not needed; just to illustrate
iterator items(a: Foo): int = discard
template bar(a: iterable[int]) = echo "in bar"
var x: Foo
bar(x.items)
bar(x.mitems)
bar(x)note 1
this would cause infinite loop in compiler, and even if it were fixed, would be a worse solution as converters have a more subversive side effect on type system
converter toIterable*[T](a: Iterable[T]): iterable = items(a)