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 <[email protected]> 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 <[email protected] 
> <mailto:[email protected]>> wrote:
> 
>> On 7 May 2017, at 10:30, Xiaodi Wu <[email protected] 
>> <mailto:[email protected]>> 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 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to