[swift-evolution] [Pitch] Enumerate from offset

Ben Cohen ben_cohen at apple.com
Sun May 7 13:51:41 CDT 2017

I agree we shouldn’t have both, that would cause confusion/bloat. The downside I see of making zip a method on Sequence is that the first argument is not somehow more “special” than the second. Were it not for the chaining (and discoverability) issue, I’d be against it – it feels right as a free function. By the same rationale, would max be a method on Comparable? 

The bouncing-right-to-left issue is a more general problem, and is also a problem with feeding results into initializers. An alternative is that someday we could add the pipe-forward operator:

(note this is not a pitch, just a someday-idea :-)

// precedence would need some thought
infix operator |>

func |> <T,U>(lhs: T, rhs: (T)->U) -> U {
    return rhs(lhs)

let words = ["five","four","three","two","one","blastoff!"]
((0...5).reversed() |> { zip($0, words) })
    .forEach { print($0.0,$0.1, separator: ": ") }

Still pretty ugly though. Some language sugar (again not a pitch) might help:

((0...5).reversed() |> zip(_, words))
    .forEach { print($0.0,$0.1, separator: ": ") }

Then again, I don’t know if facilitating chaining like this is really that important. I usually find assigning to an intermediate variable to be just as readable when the chaining doesn’t quite flow right.

> On May 7, 2017, at 11:01 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> I don't see where anything is broken. It sounds like you simply prefer one style over another, which is fine but cannot justify two features in the standard library that do the same thing. As you demonstrate, you can easily write your own method if that's your preference.
> On Sun, May 7, 2017 at 04:18 Pavol Vaskovic <pali at pali.sk <mailto:pali at pali.sk>> wrote:
>> On 7 May 2017, at 10:30, Xiaodi Wu <xiaodi.wu at gmail.com <mailto:xiaodi.wu at gmail.com>> wrote:
>> Sorry, I'm confused: what is the point of adding a method that does the same thing as an existing free function? With one-sided ranges now a part of the language, I'd support removal of `enumerated()` with no other changes.
> I’m talking about scenario where you have a chain of sequence operations, say:
> (1...N).makeIterator().enumerated().lazy.prefix(while: {$0.0 < oneLess}).count()
> With a free function, you need to break the chain in order to replace enumerated with zip:
> zip((1...N).makeIterator(), 0...oneLess).lazy.prefix(while: {$0.0 < oneLess}).count()
> It forces you to rearrange your code into less than ideal order. Free function zip works great if you start with it. Not when you need to employ it in the middle of the chain. 
> (1...N).makeIterator().zipped(with: 0...oneLess).lazy.prefix(while: {$0.0 < oneLess}).count()
> Just to be clear, how much change I’m proposing here, in case we remove enumerated:
> extension Sequence {
>     func zipped<S>(with otherSequence: S) -> Zip2Sequence<Self, S> where S: Sequence {
>         return zip (self, otherSequence)
>     }
> }
> Best regards
> Pavol Vaskovic 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170507/cf2732e4/attachment.html>

More information about the swift-evolution mailing list