What are the actual use-cases where people have needed destructive iterators?
Every time I have thought I wanted it, I ended up wanting multi-pass later.
For example, I had a sequence of random numbers, but ended up having to build a
random hash instead so I could reliably re-create that sequence. The other
use-cases I can think of (e.g. markov-chains) would probably end up needing
repeatability at some point as well.
The only thing I can think of without an eventual multi-pass requirement would
be reading in an input or signal of some sort.
The most troubling thing to me is having the value type be destructive in such
a weird way.
I would like to see Iterator take a more functional approach. In addition to
the mutating next()->T? function, it would be nice to have a non-mutating
nextIterator() -> (T, Iterator<T>)?, which non-destructively returns a tuple of
the next value and an iterator set to the next step. This would be
nondestructive, so it would probably require pre-calculating the next value
early for destructive sequences. The end result would be that next value is
guaranteed to be the same whenever it is called from the non-mutated iterator,
but future values may quickly diverge (from separate copies of the value type).
The other alternative would be to make Iterator a reference type.
I would be ok with either solution. I would be most in favor of whichever
version allows us to build some sort of yielding iterator construct later.
I.e. I am going to run through this iterator until a condition is met… then
later I will pick up where I left off. This is a useful pattern, especially
for things which get destructively consumed.
I would like sequences to always be nondestructive / multi-pass, and gain
everything from collectionType except those things which require an end index
(e.g. count). Sequences could be infinite. Sequences could/would still vend
destructively consumed iterators… they would just be required to vend the exact
same iterator (which generates the same sequence of values) each time you ask
for it.
Then we have collectionType (which should be renamed FiniteSequence), which
re-gains count, dropLast, etc…. Basically the same as collectionType today.
What I like about splitting finite and potentially infinite sequences:
1) It allows compiler warnings for .forEach and for-in without break
2) You could build interesting infinite sequences, and then create a finite
sequence by adding limits/predicates (e.g. all prime numbers where x < 250)
FiniteSequence(from: infSequence, boundedBy: 0…100)
FiniteSequence(from: infSequence, stoppingWhen: {$0 % 2 == 0})
FiniteSequence(from: infSequence, maxCount: 1000) //The above may need a
maxCount parameter as well (which defaults to Int.max)
Top of my list for interesting infinite sequences would be RandomSequence,
which inits with a seed (defaulting to a random seed), and produces a
reproducible sequence of random T.
Thanks,
Jon
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution