stdlib: adds itertools, composable templates for inline iterators#25680
stdlib: adds itertools, composable templates for inline iterators#25680ZoomRmc wants to merge 6 commits intonim-lang:develfrom
itertools, composable templates for inline iterators#25680Conversation
|
Test failures all should get green after #25679. |
|
Very nice, specially that things compose and don't have to be materialized!
|
|
Thanks!
Well, it's a language omission first ( This works: let infinite = iterator(): int =
while true: yield 1
template asIterable[T](it: iterator(): T {.closure.}): untyped =
iterator wrap(): T =
for x in it():
yield x
wrap()
var sum = 0
for i in infinite.asIterable().take(3):
sum.inc i
doAssert sum == 3We could provide such template in the module, but it's a hack and we should just make
Absolutely! Otherwise, the templates wouldn't compose. Added a test case for the chain in the regular iterator context (the |
|
CI errors are unrelated timeouts now. |
|
Why is |
Araq suggested unifying closure and inline iterators. |
I don't know how that would look like, because they are inherently different. Inlines are just a syntactic sugar, but closure iterators are 1. callable 2. have state 3. enclose around stuff. This entails some serious design work. However, just making them satisfy
Adding doc comments to templates producing untyped nodes results in wrapping a call in a statement list and, as a result, type mismatch after expansion. import std/macros
macro genIter(): untyped =
quote do:
iterator tmp(): int = yield 42
tmp()
template clean(): untyped =
genIter()
template dirty(): untyped =
## A flower?
genIter()
macro dump(): untyped =
echo "CLEAN"
echo treeRepr getAst clean()
echo "\nDIRTY"
echo treeRepr getAst dirty()
dump()produces |
|
Can you check if it's a stmt list, and unwrap it if so? |
Of course, but only from a macro. You can't operate on nodes from a template. |
This PR implements RFC #562 , it was given a green light long ago.
The code is based on beef's idea and impl in
slicerator/itermacros.For convenient syntax that allows writing
"foo".split.mapIt(it).collect()and notmapIt("foo".split, it).collect()"it requires merging #25679 (or an alternative fix) but it doesn't rely on it inherently (except some examples and test cases assume this form being available), so workable even without it.This example works now:
The implementation is straightforward, API is bog-standard and shouldn't be surprising to anyone familiar with this style, tests cover everything. The only interesting thing in the code is that it uses concepts for overloads without any
when compileshacks, feels pretty great.The set of provided templates is basic and the naming is all common, so I hope there's not much place for bikeshedding. I've been craving for this feature since 2018 or so and didn't hear much pushback against the idea, so I hope this PR doesn't go to waste.
requires #25679