[swift-evolution] [Pitch] Enumerate from offset

André Videla andre.videla at gmail.com
Thu May 4 09:51:33 CDT 2017


You can do this trivially with drop. But enumerated from has one nice property:

myArray.enumerated().dropFirst(6) // counts from 6

myArray.dropFirst(6).enumerated() // counts from 0

Those two lines do very different things even though they look similar

myArray.enumerated(from: 6)
Is unambiguous 

But I don't think it is worth adding to the sequence protocol if the argument is that it's unambiguous. 

Andre Videla 

> On 4 May 2017, at 14:39, Pavol Vaskovic via swift-evolution <swift-evolution at swift.org> wrote:
> 
> Hello!
> 
> Here's a pitch to pick a small nit from the Sequence protocol:
> 
> https://github.com/palimondo/swift-evolution/blob/sequence-cleanup/proposals/NNNN-enumerate-from.md
> 
> Best regards
> Pavol Vaskovic
> 
> Enumerate from offset
> 
> Proposal: SE-NNNN
> 
> Authors: Pavol Vaskovic, Author 2
> 
> Review Manager: TBD
> 
> Status: Pitch
> 
> Bugs: SR-4746
> 
> Introduction
> 
> Let user specify the staring index for enumerated method on Sequences.
> 
> Swift-evolution thread: Discussion thread topic for that proposal
> 
> Motivation
> 
> The enumerated() method defined in an extension on protocol Sequence always counts from 0. When you need the numbers to be counting up from different index, you have to post process the resulting tuple in an inconvenient way.
> 
> Proposed solution
> 
> We could provide an option to count elements from a user specified offset:
> 
> [6, 7, 8].enumerated(from: 6)
> // [(offset: 6, element: 6), (offset: 7, element: 7), (offset: 8, element: 8)]
> If implemented with default parameter, this does not change the usage for existing code, being source compatible with Swift 3.
> 
> Detailed design
> 
> The proposed solution is to propagate the starting value to the internal counter on EnumeratedIterator and set the default starting value to 0.
> 
> public struct EnumeratedIterator<
>     Base : IteratorProtocol
> > : IteratorProtocol, Sequence {
>     internal var _base: Base
>     internal var _count: Int
>     
>     /// Construct from a `Base` iterator.
>     internal init(_base: Base, _offset: Int) {
>         self._base = _base
>         self._count = _offset
>     }
>     
>     /// The type of element returned by `next()`.
>     public typealias Element = (offset: Int, element: Base.Element)
>     
>     /// Advances to the next element and returns it, or `nil` if no next element
>     /// exists.
>     ///
>     /// Once `nil` has been returned, all subsequent calls return `nil`.
>     public mutating func next() -> Element? {
>         guard let b = _base.next() else { return nil }
>         let result = (offset: _count, element: b)
>         _count += 1
>         return result
>     }
> }
> 
> public struct EnumeratedSequence<Base : Sequence> : Sequence {
>     internal var _base: Base
>     internal let _offset: Int
>     
>     /// Construct from a `Base` sequence.
>     internal init(_base: Base, _offset: Int) {
>         self._base = _base
>         self._offset = _offset
>     }
>     
>     /// Returns an iterator over the elements of this sequence.
>     public func makeIterator() -> _EnumeratedIterator<Base.Iterator> {
>         return EnumeratedIterator(_base: _base.makeIterator(), _offset: _offset)
>     }
> }
> 
> extension Sequence {
>     public func enumerated(from: Int = 0) -> _numeratedSequence<Self> {
>         return EnumeratedSequence(_base: self, _offset: from)
>     }
> }
> Source compatibility
> 
> Proposed change is source compatible with Swift 3.
> 
> Effect on ABI stability and resilience
> 
> This change does affect the ABI and should be implemented before we freeze it.
> 
> Alternatives considered
> 
> Currently proposed workaround for the lack of flexibility in enumerated() is to use zip with the collection and half-open range. From SR-0172 One-sided Ranges:
> 
> Additionally, when the index is a countable type, i... should form a Sequence that counts up from i indefinitely. This is useful in forming variants of Sequence.enumerated() when you either want them non-zero-based i.e.zip(1..., greeting), or want to flip the order i.e. zip(greeting, 0...).
> Drawback of this approach is that you need to use free function zip, forcing a break in the chain of sequence operations, as there is currently no zipped method on Sequence.
> 
> If this is the preffered approach, we should consider removing the enumerated() method altogether, because the limited usefullness in its current state hardly justifies the space on API surface it occupies.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170504/98b500a1/attachment.html>


More information about the swift-evolution mailing list