> On Dec 19, 2015, at 1:47 PM, Brent Royal-Gordon <br...@architechies.com> 
> wrote:
> 
>>> for lat in (CGFloat(-60)...60).by(30) {
>>>  print(lat)
>>> }
>>> 
>>> for lat in (CGFloat(-60)..<60).by(30) {
>>>  print(lat)
>>> }
>> 
>> This is nice; why don't we put it in the standard library and get rid of the 
>> "stride" methods?
> 
> One practical reason is that interval.start must always be before 
> interval.end, so this makes striding in reverse difficult.

We could declare that negative strides cause us to start at the end rather than 
at the start.

> Another is that the precedence of the interval operators forces additional 
> parentheses, so the resulting code is usually ugly.

I'm aware of that, but it seems less ugly to me than the alternative, and more 
importantly it keeps the range/interval EDSL more integrated.

> (And making them higher-precedence than member access has its own problems, 
> like `0..<(foo.count)`.)
> 
> Honestly, as much as we try to avoid them, I think the old free functions in 
> Swift 1 gave us the best-looking code. Adapted to use intervals:
> 
>     for lat in stride(CGFloat(-60)…60, by: 30) {
>          print(lat)
>    }
> 
> Or, a little more cleanly:
> 
>     for lat: CGFloat in stride(-60…60, by: 30) {
>          print(lat)
>    }
> If you don’t like the function syntax, one funky alternative might be to 
> overload `+`:
> 
>     for lat: CGFloat in -60...60 + 30 {       // Meaning “increment by 30 
> each time"
>          print(lat)
>    }
> 
> Hmm. Rather than overloading, maybe we can use two recently-freed-up 
> operators which are traditionally associated with looping...
> 
>    infix operator ++ { associativity none precedence 130 }    // 130 is 
> looser than the interval operators
>    infix operator -- { associativity none precedence 130 }
> 
>    func ++ <Bound: Strideable>(interval: ClosedInterval<Bound>, stride: 
> Bound.Stride) -> StrideThrough<Bound> {
>        // These implementations are just how they work against the current 
> public API, of course.
>        return interval.start.stride(through: interval.end, by: stride)
>    }
> 
>    func ++ <Bound: Strideable>(interval: HalfOpenInterval<Bound>, stride: 
> Bound.Stride) -> StrideTo<Bound> {
>        return interval.start.stride(to: interval.end, by: stride)
>    }
> 
>    func -- <Bound: Strideable>(interval: ClosedInterval<Bound>, stride: 
> Bound.Stride) -> StrideThrough<Bound> {
>        return interval.end.stride(through: interval.start, by: -stride)
>    }
> 
>    func -- <Bound: Strideable>(interval: HalfOpenInterval<Bound>, stride: 
> Bound.Stride) -> StrideTo<Bound> {
>        return interval.end.stride(to: interval.start, by: -stride)
>    }
> 
> Giving you:
> 
>    // Counts up from start by 30
>    for lat: CGFloat in -60...60 ++ 30 {
>        print(lat)
>    }
> 
>    // Counts down from end by 30
>    for lat: CGFloat in -60...60 -- 30 {
>        print(lat)
>    }
> 
> Perhaps this could even be extended to take a Bound -> Bound function as the 
> right-hand parameter, allowing for the sort of arbitrary incrementing that 
> some complain we've lost without C-style for:
> 
>    for lat: CGFloat in 1...60 ++ { $0 * 2 } {
>        print(lat)
>    }
> 
> And, of course, we could also provide unary variants which do +1 and -1:
> 
>    // Counts up from start by 1
>    for lat: CGFloat in -60...60++ {
>        print(lat)
>    }
> 
>    // Counts down from end by 1
>    for lat: CGFloat in -60...60-- {
>        print(lat)
>    }


None of those syntaxes fly for me, I'm afraid.  They all look like line noise 
(and some have precedence problems); I much prefer requiring a set of 
parentheses.

-Dave



_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to