[swift-evolution] Proposal: Add scan, takeWhile, dropWhile, and iterate to the stdlib
Thorsten Seitz
tseitz42 at icloud.com
Sun Mar 6 09:10:46 CST 2016
> Am 06.03.2016 um 06:38 schrieb Dave Abrahams via swift-evolution <swift-evolution at swift.org>:
>
>
>> on Mon Dec 28 2015, Kevin Ballard <swift-evolution-AT-swift.org> wrote:
>>
>> ## Introduction
>>
>> Add a few more functional sequence utilities to the standard library.
>>
>> ## Motivation
>>
>> We have map, filter, and reduce, but we're missing a bunch of useful
>> utilities like scan, iterate, takeWhile, and dropWhile. Interestingly,
>> the stdlib includes an implementation of scan in the doc comment for
>> LazySequenceType, it just doesn't actually provide it as API.
>
> One of my concerns here is that while map, filter, and reduce are mostly
> “lingua franca” terms-of-art among programmers everywhere, these others
> are much less commonly-known and some of them aren't very descriptive of
> what they do. There are lots more like these in the FP lexicon. It was
I for one would love to see them added to the stdlib.
-Thorsten
> easy to draw the line at map/filter/reduce (which also don't follow the
> usual grammar for API guidelines), but if we take the ones in this
> proposal, where do we stop?
>
> Because your PR has comments describing these methods (i.e. it's more
> complete) I'll leave further remarks there.
>
>>
>> ## Proposed solution
>>
>> We extend SequenceType with 3 new methods scan, takeWhile, and dropWhile. We also add a single global function iterate.
>>
>> ## Detailed design
>>
>> We add the following extension to SequenceType:
>>
>> extension SequenceType {
>> func scan<T>(initial: T, @noescape combine: (T, Self.Generator.Element) throws -> T) rethrows -> [T]
>> func dropWhile(@noescape dropElement: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.Generator.Element]
>> func takeWhile(@noescape takeElement: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.Generator.Element]
>> }
>>
>> These all take functions, so to follow convention they're @noescape
>> and return arrays. We also provide an extension of CollectionType that
>> overrides a couple of these methods:
>>
>> extension CollectionType {
>> func dropWhile(@noescape dropElement: (Self.Generator.Element) throws -> Bool) rethrows -> Self.SubSequence
>> func takeWhile(@noescape takeElement: (Self.Generator.Element) throws -> Bool) rethrows -> Self.SubSequence
>> }
>>
>> We also provide lazy versions:
>>
>> extension LazySequenceType {
>> func scan<T>(initial: T, combine: (T, Self.Generator.Element) -> T) -> LazyScanSequence<Self.Elements, T>
>> func dropWhile(dropElement: (Self.Generator.Element) -> Bool) -> LazyDropWhileSequence<Self.Elements>
>> func takeWhile(takeElement: (Self.Generator.Element) -> Bool) -> LazyTakeWhileSequence<Self.Elements>
>> }
>>
>> extension LazyCollectionType {
>> func dropWhile(dropElement: (Self.Generator.Element) -> Bool) -> LazyDropWhileCollection<Self.Elements>
>> func takeWhile(takeElement: (Self.Generator.Element) -> Bool) -> LazyTakeWhileCollection<Self.Elements>
>> }
>>
>> No collection variant of scan is provided because that would require
>> storing the last value in the index itself, which would cause problems
>> if the combine function isn't pure.
>>
>> LazyDropWhileCollection would behave similarly to LazyFilterCollection
>> in that it runs the predicate against the elements to drop when
>> accessing startIndex; unlike LazyFilterCollection, because there's
>> nothing else to skip after that point, the index itself can actually
>> be Self.Elements.Index (just like a slice). LazyTakeWhileCollection
>> also runs the predicate against the first element when accessing
>> startIndex, but it does need a unique index type (because endIndex has
>> to be some sentinel value, as it doesn't know where the end is until
>> you reach that point; this index type would therefore only conform to
>> ForwardIndexType).
>>
>> And finally, we provide a global function
>>
>> func iterate<T>(initial: T, _ f: T -> T) -> IterateSequence<T>
>>
>> This function is inherently lazy and yields an infinite list of nested
>> applications of the function, so iterate(x, f) yields a sequence like
>> [x, f(x), f(f(x)), ...].
>>
>> -Kevin Ballard
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> --
> -Dave
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
More information about the swift-evolution
mailing list