Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-25 Thread Erica Sadun via swift-evolution
On Apr 25, 2016, at 7:15 PM, Xiaodi Wu via swift-evolution 
 wrote:
> 
> Yup, we're going to try to touch base, the authors of the current draft that 
> is, sometime this week. More to come, hopefully.
> 
> 
> On Mon, Apr 25, 2016 at 8:13 PM, Dave Abrahams via swift-evolution 
> > wrote:
> After some reflection, I don't really want to see a construct like #3 in
> the standard library, and Chris has clarified for me that the standard
> library doesn't need to solve the migration problems created by the
> removal of C-style “for” loops.  So, if I have inadvertently killed
> progress on this proposal by bringing it up, please allow me to retract
> item 3 above.

* Strides break down into: walks along the integer number line and walks along 
the floating
point number line. We need to fix the math

* For in need to work for collections, integer ranges, and strides for basic 
iteration.

* Advanced `for` work is already addressed with mapping and Kevin Ballard's 
proposed iterate and takeWhile

* Everyone but me has been traveling so getting things together has been a 
little hard.

* I have been on Nate's case a lot about what collections, strides, sequences, 
etc mean and should be named.

-- E

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-25 Thread Xiaodi Wu via swift-evolution
Yup, we're going to try to touch base, the authors of the current draft
that is, sometime this week. More to come, hopefully.


On Mon, Apr 25, 2016 at 8:13 PM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Mon Apr 11 2016, Dave Abrahams  wrote:
>
> > on Sun Apr 10 2016, Michel Fortin  wrote:
> >
> >> So if you take this into account, storing the comparator as part of
> >> the stride makes the cost more predictable: not only there is one
> >> branch less in `next()`, but you avoid evaluating the condition which
> >> has an unknown cost: the `stride < 0` part.
> >>
> >> And ideally you should make sure the optimizer can replace the
> >> indirect call with a direct call to the comparator. You do that by not
> >> making the comparator choice dependent on a runtime value, hence why I
> >> suggested having distinct "down" variants for the convenience
> >> functions: `stride(from:downTo:by:)` and
> >> `stride(from:downThrough:by:)` and `Range.strindingDown(by:)`.
> >
> > A few points:
> >
> > 1. There's a balance to be struck between making sure the optimizer can
> >do a good job under *absolutely all circumstances*, and keeping the
> >API surface area small and simple.  That makes me somewhat reluctant
> >to add “down” variants, if as I suspect the optimizer does well in
> >the vast majority of cases without them.
> >
> > 2. Similarly, I view r.striding(by: x) as redundant with stride(from: x,
> >to: y, by: z).  I'd rather not have them both.
> >
> > 3. The fact that we're migrating C-style for loops to
> >uses of stride, as noted in https://github.com/apple/swift/pull/2125,
> >has convinced me that, sadly, we may need an answer that doesn't
> >involve ranges.  But maybe something like
> >
> >  for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
> >
> >is sufficient for this purpose.
>
> After some reflection, I don't really want to see a construct like #3 in
> the standard library, and Chris has clarified for me that the standard
> library doesn't need to solve the migration problems created by the
> removal of C-style “for” loops.  So, if I have inadvertently killed
> progress on this proposal by bringing it up, please allow me to retract
> item 3 above.
>
> I'd love to see the floating-point stride thing solved for Swift 3, but
> the window for changes is getting narrower, so if the community wants to
> move forward with the proposal (and implementation), that would be
> awesome.
>
> Cheers,
>
> --
> Dave
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-25 Thread Dave Abrahams via swift-evolution

on Mon Apr 11 2016, Dave Abrahams  wrote:

> on Sun Apr 10 2016, Michel Fortin  wrote:
>
>> So if you take this into account, storing the comparator as part of
>> the stride makes the cost more predictable: not only there is one
>> branch less in `next()`, but you avoid evaluating the condition which
>> has an unknown cost: the `stride < 0` part.
>>
>> And ideally you should make sure the optimizer can replace the
>> indirect call with a direct call to the comparator. You do that by not
>> making the comparator choice dependent on a runtime value, hence why I
>> suggested having distinct "down" variants for the convenience
>> functions: `stride(from:downTo:by:)` and
>> `stride(from:downThrough:by:)` and `Range.strindingDown(by:)`.
>
> A few points:
>
> 1. There's a balance to be struck between making sure the optimizer can
>do a good job under *absolutely all circumstances*, and keeping the
>API surface area small and simple.  That makes me somewhat reluctant
>to add “down” variants, if as I suspect the optimizer does well in
>the vast majority of cases without them.
>
> 2. Similarly, I view r.striding(by: x) as redundant with stride(from: x,
>to: y, by: z).  I'd rather not have them both.
>
> 3. The fact that we're migrating C-style for loops to
>uses of stride, as noted in https://github.com/apple/swift/pull/2125,
>has convinced me that, sadly, we may need an answer that doesn't
>involve ranges.  But maybe something like
>
>  for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
>
>is sufficient for this purpose.

After some reflection, I don't really want to see a construct like #3 in
the standard library, and Chris has clarified for me that the standard
library doesn't need to solve the migration problems created by the
removal of C-style “for” loops.  So, if I have inadvertently killed
progress on this proposal by bringing it up, please allow me to retract
item 3 above.  

I'd love to see the floating-point stride thing solved for Swift 3, but
the window for changes is getting narrower, so if the community wants to
move forward with the proposal (and implementation), that would be
awesome.

Cheers,

-- 
Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-19 Thread Thorsten Seitz via swift-evolution
I agree with Taras that stride() and .striding() should coexist. 

-Thorsten 

> Am 09.04.2016 um 01:01 schrieb Taras Zakharko via swift-evolution 
> :
> 
> I am agnostic on a .striding() method, but I am strongly agains any 
> suggestions of removing/replacing the global stride() function. The stride 
> function does not pollute the global namespace as it is a universally useful 
> construct (among others, for implementing classical iterating for loops), has 
> its history in contemporary programming (comparable functions in languages 
> like Python, R), and is IMO more readable and clear than a range with a 
> striding method method. Furthermore, a stride is not a range — its a special 
> sequence, while for ranges other rules apply. All in all, I don’t see why 
> stride() and .striding() can’t coexist. 
> 
> — Taras 
> 
> P.S. As a side note, I would prefer if the stride() function be renamed 
> sequence() or seq(), but thats just cosmetic personal preference. 
> 
> 
>> On 08 Apr 2016, at 20:37, Erica Sadun via swift-evolution 
>>  wrote:
>> 
>> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307  
>> Feedback solicited, both positive and negative. 
>> We've also got a related proposal about expanding ranges, which you can look 
>> at here (https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9)
>>  but we want to float this one first.
>> 
>> Thanks, -- E
>> 
>> 
>> 
>> Proposal: SE-
>> Author(s): Xiaodi Wu, Pyry Jahkola, Nate Cook, Erica Sadun
>> Status: TBD
>> Review manager: TBD
>> Introduction
>> 
>> We propose to introduce a striding(by:) method on the revised 3.0 Range type.
>> 
>> This proposal was discussed on the Swift Evolution list in the Feature 
>> proposal: Range operator with step thread. (Direct link to original thread)
>> 
>> Motivation
>> 
>> Updating Range for Swift 3 offers a window of opportunity to simultaneously 
>> improve strides.
>> 
>> Under current Swift 3 plans, n.stride(to:/through:, by:) will be replaced 
>> with a standalone stride(from:, to:/through:, by:) function. We propose to 
>> replace this change with a method on ranges. Using a method reduces overall 
>> API surface area compared to free functions.
>> 
>> In its current incarnation, the standalone stride function uses confusing 
>> semantics. The current to implementation returns values in [start, end) and 
>> will never reach or get to end. The current through implementation returns 
>> values in [start, end]. It may never reach end and certainly never goes 
>> through that value. Our proposed method introduces simple, expected 
>> semantics that can be extended to both countable and continuous ranges, and 
>> to open and closed intervals (both half-open and fully-open).
>> 
>> Detail Design
>> 
>> The striding(by:) method is called on ranges. When used with a positive step 
>> size, the count starts from the lower bound. With a negative step size, the 
>> count starts from the upper bound. These bounds apply regardless of whether 
>> they are inclusive or exclusive. 
>> 
>> The following examples should cover all corner cases and include possible 
>> cases should Swift 3 introduce a full complement of open and closed ranges. 
>> The syntax for non-canonical range types is not fixed and can be discussed 
>> under separate cover.
>> 
>> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
>> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
>> (0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
>> (0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]
>> 
>> (0 ... 9).striding(by: 3) == [0, 3, 6, 9]
>> (0 ..< 9).striding(by: 3) == [0, 3, 6]
>> (0 <.. 9).striding(by: 3) ==[3, 6, 9]
>> (0 <.< 9).striding(by: 3) ==[3, 6]
>> 
>> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
>> (0 ..< 9).striding(by: -2) ==[7, 5, 3, 1]
>> (0 <.. 9).striding(by: -2) == [9, 7, 5, 3, 1]
>> (0 <.< 9).striding(by: -2) ==[7, 5, 3, 1]
>> 
>> (0 ... 9).striding(by: -3) == [9, 6, 3, 0]
>> (0 ..< 9).striding(by: -3) ==[6, 3, 0]
>> (0 <.. 9).striding(by: -3) == [9, 6, 3]
>> (0 <.< 9).striding(by: -3) ==[6, 3]
>> To reverse a stride, call reverse() on the results:
>> 
>> (0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]
>> We note that striding by 0 should be always be a precondition failure.
>> 
>> Alternatives Considered
>> 
>> During the on-list discussion, we considered various scenarios that took 
>> closed/inclusive bounds into account or excluded open bounds for starting 
>> values. For example, we might have prohibited scenarios where multiple 
>> interpretations of an intended behavior might exist: is (0 ..< 
>> 9).striding(by: -2) a precondition failure? We settled on the simplest, most 
>> straight-forward implementation involving the fewest compiler warnings and 
>> the lowest likelihood of precondition failures. We subscribe to the "Dave 
>> Abrahams Philosophy": excessive special casing and warning scenarios more 
>> likely indicates bad 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Nate Cook via swift-evolution

> On Apr 11, 2016, at 6:49 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> on Mon Apr 11 2016, Ross O'Brien  wrote:
> 
>> I think I'd like to +1 a 'for x in loop(from: while: next:)'. (Possibly
>> 'iterate' rather than 'loop'?)
> 
> Maybe 'iterations'.  It should be a noun, I think.

There's a proposal awaiting review right now that would add an iterate function 
and takeWhile sequence method, so these could be written as:

for x in iterate(0.1, apply: { $0 + 2 }).takeWhile({ $0 < 10 }) {
// ...
}

and

for view in iterate(startingSubview, apply: { $0.superview }).takeWhile({ $0 != 
nil }) {
// ...
}

If the iterate function were overloaded with a while argument, this would be 
exactly what we're discussing. Perhaps this proposal should be a jumping off 
point?

https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
 


Nate


>> I've not missed the C-style for-loop so I've not argued to keep it, but 
>> recently
>> I was refactoring a function which started with a UIView and iterated up the
>> hierarchy through the superview property, and it occurred to me recently that
>> neither stride nor sequences/generators handle recursive iterations well.
>> 
>> So, I imagine that would look like this:
>> for view in loop(from: startingSubview, while: { $0 != nil }, next: { $0 =
>> $0.superview })
>> 
>> On Mon, Apr 11, 2016 at 11:31 PM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>>on Mon Apr 11 2016, Michel Fortin  wrote:
>> 
>>> Le 11 avr. 2016 à 14:36, Dave Abrahams
>> a écrit :
>>> 
 3. The fact that we're migrating C-style for loops to
 uses of stride, as noted in https://github.com/apple/swift/pull/2125,
 has convinced me that, sadly, we may need an answer that doesn't
 involve ranges. But maybe something like
 
 for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
 
 is sufficient for this purpose.
>>> 
>>> Please add that.
>> 
>>Please write a proposal and ideally, submit a patch :-).
>> 
>>Seriously, if this is something you believe in, we could really use the
>>help.
>> 
>>> First, it would relieve `stride` from some of the pressure of
>>> excelling at replacing existing C-style for loops. But it would also
>>> become pretty easy to write custom sequences like this one:
>>> 
>>> func uniform(start: Double, end: Double, numberOfSteps totalSteps: Int) ->
>>Sequence {
>>> var currentStep = 0
>>> return loop(from: start, while: { _ in
>>> currentStep < totalSteps
>>> }, next: { _ in
>>> currentStep += 1
>>> return start * (Double(totalSteps-currentStep) / Double(totalSteps)) +
>>> end * (Double(currentStep) / Double(totalSteps))
>>> })
>>> }
>> 
>>Aside from the fact that you can't return Sequence, this seems like a
>>much better way to do that in Swift 3.0:
>> 
>>func uniform(
>>start: Double, end: Double, numberOfSteps totalSteps: Int
>>) -> LazyMapRandomAccessCollection {
>>return (0..>start * (Double(totalSteps-$0) / Double(totalSteps)) +
>>end * (Double($0) / Double(totalSteps))
>>}
>>}
>> 
>>--
>>Dave
>> 
>>___
>>swift-evolution mailing list
>>swift-evolution@swift.org
>>https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> -- 
> Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Dave Abrahams via swift-evolution

on Mon Apr 11 2016, Ross O'Brien  wrote:

> I think I'd like to +1 a 'for x in loop(from: while: next:)'. (Possibly
> 'iterate' rather than 'loop'?)

Maybe 'iterations'.  It should be a noun, I think.

> I've not missed the C-style for-loop so I've not argued to keep it, but 
> recently
> I was refactoring a function which started with a UIView and iterated up the
> hierarchy through the superview property, and it occurred to me recently that
> neither stride nor sequences/generators handle recursive iterations well.
>
> So, I imagine that would look like this:
> for view in loop(from: startingSubview, while: { $0 != nil }, next: { $0 =
> $0.superview })
>
> On Mon, Apr 11, 2016 at 11:31 PM, Dave Abrahams via swift-evolution
>  wrote:
>
> on Mon Apr 11 2016, Michel Fortin  wrote:
>
> > Le 11 avr. 2016 à 14:36, Dave Abrahams
>  a écrit :
> >
> >> 3. The fact that we're migrating C-style for loops to
> >> uses of stride, as noted in https://github.com/apple/swift/pull/2125,
> >> has convinced me that, sadly, we may need an answer that doesn't
> >> involve ranges. But maybe something like
> >>
> >> for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
> >>
> >> is sufficient for this purpose.
> >
> > Please add that.
>
> Please write a proposal and ideally, submit a patch :-).
>
> Seriously, if this is something you believe in, we could really use the
> help.
>
> > First, it would relieve `stride` from some of the pressure of
> > excelling at replacing existing C-style for loops. But it would also
> > become pretty easy to write custom sequences like this one:
> >
> > func uniform(start: Double, end: Double, numberOfSteps totalSteps: Int) 
> ->
> Sequence {
> > var currentStep = 0
> > return loop(from: start, while: { _ in
> > currentStep < totalSteps
> > }, next: { _ in
> > currentStep += 1
> > return start * (Double(totalSteps-currentStep) / Double(totalSteps)) +
> > end * (Double(currentStep) / Double(totalSteps))
> > })
> > }
>
> Aside from the fact that you can't return Sequence, this seems like a
> much better way to do that in Swift 3.0:
>
> func uniform(
> start: Double, end: Double, numberOfSteps totalSteps: Int
> ) -> LazyMapRandomAccessCollection {
> return (0.. start * (Double(totalSteps-$0) / Double(totalSteps)) +
> end * (Double($0) / Double(totalSteps))
> }
> }
>
> --
> Dave
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-- 
Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Ross O'Brien via swift-evolution
I think I'd like to +1 a 'for x in loop(from: while: next:)'. (Possibly
'iterate' rather than 'loop'?)

I've not missed the C-style for-loop so I've not argued to keep it, but
recently I was refactoring a function which started with a UIView and
iterated up the hierarchy through the superview property, and it occurred
to me recently that neither stride nor sequences/generators handle
recursive iterations well.

So, I imagine that would look like this:
for view in loop(from: startingSubview, while: { $0 != nil }, next: { $0 =
$0.superview })


On Mon, Apr 11, 2016 at 11:31 PM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Mon Apr 11 2016, Michel Fortin  wrote:
>
> > Le 11 avr. 2016 à 14:36, Dave Abrahams  a écrit :
> >
> >> 3. The fact that we're migrating C-style for loops to
> >>   uses of stride, as noted in https://github.com/apple/swift/pull/2125,
> >>   has convinced me that, sadly, we may need an answer that doesn't
> >>   involve ranges.  But maybe something like
> >>
> >> for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
> >>
> >>   is sufficient for this purpose.
> >
> > Please add that.
>
> Please write a proposal and ideally, submit a patch :-).
>
> Seriously, if this is something you believe in, we could really use the
> help.
>
> > First, it would relieve `stride` from some of the pressure of
> > excelling at replacing existing C-style for loops. But it would also
> > become pretty easy to write custom sequences like this one:
> >
> > func uniform(start: Double, end: Double, numberOfSteps totalSteps: Int)
> -> Sequence {
> >   var currentStep = 0
> >   return loop(from: start, while: { _ in
> >   currentStep < totalSteps
> >   }, next: { _ in
> >   currentStep += 1
> >   return start * (Double(totalSteps-currentStep) /
> Double(totalSteps)) +
> >   end * (Double(currentStep) / Double(totalSteps))
> >   })
> > }
>
> Aside from the fact that you can't return Sequence, this seems like a
> much better way to do that in Swift 3.0:
>
> func uniform(
>   start: Double, end: Double, numberOfSteps totalSteps: Int
> ) -> LazyMapRandomAccessCollection {
>   return (0..  start * (Double(totalSteps-$0) / Double(totalSteps)) +
>  end * (Double($0) / Double(totalSteps))
>   }
> }
>
> --
> Dave
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Dave Abrahams via swift-evolution

on Mon Apr 11 2016, Michel Fortin  wrote:

> Le 11 avr. 2016 à 14:36, Dave Abrahams  a écrit :
>
>> 3. The fact that we're migrating C-style for loops to
>>   uses of stride, as noted in https://github.com/apple/swift/pull/2125,
>>   has convinced me that, sadly, we may need an answer that doesn't
>>   involve ranges.  But maybe something like
>> 
>> for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
>> 
>>   is sufficient for this purpose.
>
> Please add that. 

Please write a proposal and ideally, submit a patch :-).

Seriously, if this is something you believe in, we could really use the
help.

> First, it would relieve `stride` from some of the pressure of
> excelling at replacing existing C-style for loops. But it would also
> become pretty easy to write custom sequences like this one:
>
> func uniform(start: Double, end: Double, numberOfSteps totalSteps: Int) -> 
> Sequence {
>   var currentStep = 0
>   return loop(from: start, while: { _ in
>   currentStep < totalSteps
>   }, next: { _ in
>   currentStep += 1
>   return start * (Double(totalSteps-currentStep) / 
> Double(totalSteps)) +
>   end * (Double(currentStep) / Double(totalSteps))
>   })
> }

Aside from the fact that you can't return Sequence, this seems like a
much better way to do that in Swift 3.0:

func uniform(
  start: Double, end: Double, numberOfSteps totalSteps: Int
) -> LazyMapRandomAccessCollection {
  return (0..

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Michel Fortin via swift-evolution
Le 11 avr. 2016 à 14:36, Dave Abrahams  a écrit :

> 3. The fact that we're migrating C-style for loops to
>   uses of stride, as noted in https://github.com/apple/swift/pull/2125,
>   has convinced me that, sadly, we may need an answer that doesn't
>   involve ranges.  But maybe something like
> 
> for x in loop(from: 0.1, while: { $0 < 10 }, next: { $0 + .2 })
> 
>   is sufficient for this purpose.

Please add that. First, it would relieve `stride` from some of the pressure of 
excelling at replacing existing C-style for loops. But it would also become 
pretty easy to write custom sequences like this one:

func uniform(start: Double, end: Double, numberOfSteps totalSteps: Int) -> 
Sequence {
var currentStep = 0
return loop(from: start, while: { _ in
currentStep < totalSteps
}, next: { _ in
currentStep += 1
return start * (Double(totalSteps-currentStep) / 
Double(totalSteps)) +
end * (Double(currentStep) / Double(totalSteps))
})
}

Just don't call the function `loop`, as it does not return a loop.

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Xiaodi Wu via swift-evolution
Fair enough. If we go this direction, there's little sense in conforming
StrideTo and friends to Collection at the moment, I suppose?
On Mon, Apr 11, 2016 at 9:56 PM Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Mon Apr 11 2016, Xiaodi Wu  wrote:
>
> > I realize what follows is actually an argument for restricting stride to
> > collections with randomly accessible elements, and maybe we should:
> >
> > We've touched a little bit on performance, and I think my feeling with
> stride is
> > that just the name itself suggests a certain logic--namely, that we
> actually
> > skip over, rather than visit and discard, the elements that aren't in the
> > sequence.
> >
> > I form this intuition from the ordinary sense of the word "stride"--if my
> > walking gait has a stride size of two feet and there's a puddle less
> than one
> > foot wide right in front of me, striding by two feet means that my feet
> stay
> > dry. It doesn't mean I drag one shoe through the puddle and ignore it.
> Likewise,
> > when I stride from 2 to 10 by 2, I'm adding two at every step, not
> adding one
> > twice.
> >
> > Since an ordinary user of stride doesn't and shouldn't have to inspect
> the code
> > in the stride iterator, I think it would violate some users'
> expectations if
> > sequences that are not collections have each element visited regardless
> of
> > stride size. A user can trivially write a for loop iterating over the
> sequence
> > itself and discard every not-nth element. We shouldn't offer a stride
> function
> > that looks more performant but actually isn't.
>
> I don't see how stride neessarily has performance implications any more
> than other algorithms we also provide for Sequences, and in this case
> there's even less argument for restricting it.  Advancing is still a
> constant factor of the cost of advancing through the underlying
> Sequence.  We wouldn't even be able to offer a better big-O performance
> bound for restricting it to RandomAccessCollections.
>
> >
> > On Mon, Apr 11, 2016 at 7:38 PM Dave Abrahams
> >  wrote:
> >
> > on Sun Apr 10 2016, Xiaodi Wu  wrote:
> >
> > > On Sun, Apr 10, 2016 at 3:58 PM, Haravikk
> >  wrote:
> > >>
> > >> On 10 Apr 2016, at 14:25, Xiaodi Wu
> >  wrote:
> > >>
> > >> What types do you have in mind that would only support positive
> > distances?
> > >> All numeric types (yes, even UInt, etc.) have signed distances,
> which
> > >
> > >> reflects the basic mathematical abstraction of a number line.
> > >>
> > >>
> > >> Say you wanted to stride through a singly-linked list, it would
> actually
> > be
> > >> beneficial to support only forward strides, the same is true of
> > sequences,
> > >> as you either may not know what the endpoint is, or would have to
> step
> > >> through the whole sequence to find it (plus buffer every value in
> order
> > to
> > >> do-so safely).
> > >>
> > >> A consistent behavior with signed distances is so important that
> we are
> > >> currently struggling with an interesting issue with floating
> point types,
> > >> which is that due to rounding error 10.0 + a - a != 10.0 for some
> values
> > of
> > >> a.
> > >>
> > >>
> > >> While that’s interesting I’m not sure why the sign is important;
> to me a
> > >> stride is a width so it being negative makes no sense. For
> example, say I
> > >> laid an array of Ints, organised into groups of five (and also
> that I’m
> > >> lunatic who won’t use a tuple for this), the stride of this array
> is 5
> > >> whether I’m stepping through it forwards or backwards. Imagine I
> defined
> > >> this like so (more realistically it’d be a struct or a class):
> > >>
> > >> typealias StridedIntegerArray:(stride:Int, array:[Int])
> > >>
> > >> If the stride is set to 5, it’s always 5, the only thing that
> changes is
> > >> whether I want to stride from the start or end of the array, plus
> I could
> > >> things like:
> > >>
> > >> myStridedIntegerArray.prefix(from: 2).striding(forwardBy:
> > >> myStridedIntegerArray.stride) // Returns element at index 2, 7,
> 12, etc.
> > >
> > > When you have a sequence returning elements at index 12, 7, 2,
> etc.,
> > > wouldn't you call the stride size -5? I would, because 12 + (-5) =
> 7.
> > >
> > >>
> > >>
> > >> It just occurred to me that perhaps you intended this method only
> for
> > ranges
> > >> specifically and that perhaps I’m confusing things, but it seems
> to me
> > like
> > >> it should be a method for all sequences (with reverse stride
> available on
> > >> collections with a reverse index type) returning a generator that
> only
> > >> returns (or computes) every Nth element, for generic
> > 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Dave Abrahams via swift-evolution

on Mon Apr 11 2016, Xiaodi Wu  wrote:

> I realize what follows is actually an argument for restricting stride to
> collections with randomly accessible elements, and maybe we should:
>
> We've touched a little bit on performance, and I think my feeling with stride 
> is
> that just the name itself suggests a certain logic--namely, that we actually
> skip over, rather than visit and discard, the elements that aren't in the
> sequence.
>
> I form this intuition from the ordinary sense of the word "stride"--if my
> walking gait has a stride size of two feet and there's a puddle less than one
> foot wide right in front of me, striding by two feet means that my feet stay
> dry. It doesn't mean I drag one shoe through the puddle and ignore it. 
> Likewise,
> when I stride from 2 to 10 by 2, I'm adding two at every step, not adding one
> twice.
>
> Since an ordinary user of stride doesn't and shouldn't have to inspect the 
> code
> in the stride iterator, I think it would violate some users' expectations if
> sequences that are not collections have each element visited regardless of
> stride size. A user can trivially write a for loop iterating over the sequence
> itself and discard every not-nth element. We shouldn't offer a stride function
> that looks more performant but actually isn't.

I don't see how stride neessarily has performance implications any more
than other algorithms we also provide for Sequences, and in this case
there's even less argument for restricting it.  Advancing is still a
constant factor of the cost of advancing through the underlying
Sequence.  We wouldn't even be able to offer a better big-O performance
bound for restricting it to RandomAccessCollections.

>
> On Mon, Apr 11, 2016 at 7:38 PM Dave Abrahams
>  wrote:
>
> on Sun Apr 10 2016, Xiaodi Wu  wrote:
>
> > On Sun, Apr 10, 2016 at 3:58 PM, Haravikk
>  wrote:
> >>
> >> On 10 Apr 2016, at 14:25, Xiaodi Wu
>  wrote:
> >>
> >> What types do you have in mind that would only support positive
> distances?
> >> All numeric types (yes, even UInt, etc.) have signed distances, which
> >
> >> reflects the basic mathematical abstraction of a number line.
> >>
> >>
> >> Say you wanted to stride through a singly-linked list, it would 
> actually
> be
> >> beneficial to support only forward strides, the same is true of
> sequences,
> >> as you either may not know what the endpoint is, or would have to step
> >> through the whole sequence to find it (plus buffer every value in order
> to
> >> do-so safely).
> >>
> >> A consistent behavior with signed distances is so important that we are
> >> currently struggling with an interesting issue with floating point 
> types,
> >> which is that due to rounding error 10.0 + a - a != 10.0 for some 
> values
> of
> >> a.
> >>
> >>
> >> While that’s interesting I’m not sure why the sign is important; to me 
> a
> >> stride is a width so it being negative makes no sense. For example, 
> say I
> >> laid an array of Ints, organised into groups of five (and also that I’m
> >> lunatic who won’t use a tuple for this), the stride of this array is 5
> >> whether I’m stepping through it forwards or backwards. Imagine I 
> defined
> >> this like so (more realistically it’d be a struct or a class):
> >>
> >> typealias StridedIntegerArray:(stride:Int, array:[Int])
> >>
> >> If the stride is set to 5, it’s always 5, the only thing that changes 
> is
> >> whether I want to stride from the start or end of the array, plus I 
> could
> >> things like:
> >>
> >> myStridedIntegerArray.prefix(from: 2).striding(forwardBy:
> >> myStridedIntegerArray.stride) // Returns element at index 2, 7, 12, 
> etc.
> >
> > When you have a sequence returning elements at index 12, 7, 2, etc.,
> > wouldn't you call the stride size -5? I would, because 12 + (-5) = 7.
> >
> >>
> >>
> >> It just occurred to me that perhaps you intended this method only for
> ranges
> >> specifically and that perhaps I’m confusing things, but it seems to me
> like
> >> it should be a method for all sequences (with reverse stride available 
> on
> >> collections with a reverse index type) returning a generator that only
> >> returns (or computes) every Nth element, for generic
> sequences/collections
> >> this would take the start or end index and use advanced(by:), though
> again,
> >> I kind of feel like that should be two separate methods as well, but
> that’s
> >> for another issue I think.
> >
> > I don't think it should be for ranges only, but ranges are the extent
> > of this proposal.
> >
> > That said, my own opinion is that striding should not be available on
> > sequences but on 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Xiaodi Wu via swift-evolution
I realize what follows is actually an argument for restricting stride to
collections with randomly accessible elements, and maybe we should:

We've touched a little bit on performance, and I think my feeling with
stride is that just the name itself suggests a certain logic--namely, that
we actually skip over, rather than visit and discard, the elements that
aren't in the sequence.

I form this intuition from the ordinary sense of the word "stride"--if my
walking gait has a stride size of two feet and there's a puddle less than
one foot wide right in front of me, striding by two feet means that my feet
stay dry. It doesn't mean I drag one shoe through the puddle and ignore it.
Likewise, when I stride from 2 to 10 by 2, I'm adding two at every step,
not adding one twice.

Since an ordinary user of stride doesn't and shouldn't have to inspect the
code in the stride iterator, I think it would violate some users'
expectations if sequences that are not collections have each element
visited regardless of stride size. A user can trivially write a for loop
iterating over the sequence itself and discard every not-nth element. We
shouldn't offer a stride function that looks more performant but actually
isn't.

On Mon, Apr 11, 2016 at 7:38 PM Dave Abrahams  wrote:

>
> on Sun Apr 10 2016, Xiaodi Wu  wrote:
>
> > On Sun, Apr 10, 2016 at 3:58 PM, Haravikk 
> wrote:
> >>
> >> On 10 Apr 2016, at 14:25, Xiaodi Wu  wrote:
> >>
> >> What types do you have in mind that would only support positive
> distances?
> >> All numeric types (yes, even UInt, etc.) have signed distances, which
> >
> >> reflects the basic mathematical abstraction of a number line.
> >>
> >>
> >> Say you wanted to stride through a singly-linked list, it would
> actually be
> >> beneficial to support only forward strides, the same is true of
> sequences,
> >> as you either may not know what the endpoint is, or would have to step
> >> through the whole sequence to find it (plus buffer every value in order
> to
> >> do-so safely).
> >>
> >> A consistent behavior with signed distances is so important that we are
> >> currently struggling with an interesting issue with floating point
> types,
> >> which is that due to rounding error 10.0 + a - a != 10.0 for some
> values of
> >> a.
> >>
> >>
> >> While that’s interesting I’m not sure why the sign is important; to me a
> >> stride is a width so it being negative makes no sense. For example, say
> I
> >> laid an array of Ints, organised into groups of five (and also that I’m
> >> lunatic who won’t use a tuple for this), the stride of this array is 5
> >> whether I’m stepping through it forwards or backwards. Imagine I defined
> >> this like so (more realistically it’d be a struct or a class):
> >>
> >> typealias StridedIntegerArray:(stride:Int, array:[Int])
> >>
> >> If the stride is set to 5, it’s always 5, the only thing that changes is
> >> whether I want to stride from the start or end of the array, plus I
> could
> >> things like:
> >>
> >> myStridedIntegerArray.prefix(from: 2).striding(forwardBy:
> >> myStridedIntegerArray.stride) // Returns element at index 2, 7, 12, etc.
> >
> > When you have a sequence returning elements at index 12, 7, 2, etc.,
> > wouldn't you call the stride size -5? I would, because 12 + (-5) = 7.
> >
> >>
> >>
> >> It just occurred to me that perhaps you intended this method only for
> ranges
> >> specifically and that perhaps I’m confusing things, but it seems to me
> like
> >> it should be a method for all sequences (with reverse stride available
> on
> >> collections with a reverse index type) returning a generator that only
> >> returns (or computes) every Nth element, for generic
> sequences/collections
> >> this would take the start or end index and use advanced(by:), though
> again,
> >> I kind of feel like that should be two separate methods as well, but
> that’s
> >> for another issue I think.
> >
> > I don't think it should be for ranges only, but ranges are the extent
> > of this proposal.
> >
> > That said, my own opinion is that striding should not be available on
> > sequences but on collections only. In their most commonly used form,
> > integer strides take a start and end, and there is a finite number of
> > things to stride over; thus, in my reasoning, strides can be extended
> > to cover anything else that has a known start and end and has a finite
> > number of things, which is guaranteed by conformance to Collection but
> > not to Sequence.
>
> I dunno; it seems to me that if someone gives me a Sequence I should be
> able to traverse it, skipping every other element.  I don't see why
> “stride” should be inapplicable here.
>
> > (At the moment, StrideTo/Through conforms to Sequence and not to
> > Collection, but that is considered something to be fixed and we will
> > see if we can address that as part of this set of stride overhauls.)
> >
> > As I see it, we agree on the problem: the 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread ted van gaalen via swift-evolution
ah, you're right about that! 
somehow there was a doubly linked list in my head, sorry.

TedvG

> On 11 Apr 2016, at 11:20, Haravikk  wrote:
> 
> 
>>> On 10 Apr 2016, at 22:44, Ted F.A. van Gaalen via swift-evolution 
>>>  wrote:
>>> 
>>> Say you wanted to stride through a singly-linked list, it would actually be 
>>> beneficial to support only forward strides, the same is true of sequences, 
>>> as you either may not know what the endpoint is, or would have to step 
>>> through the whole sequence to find it (plus buffer every value in order to 
>>> do-so safely).
>> What if you are already somewhere in the middle (perhaps landed there by 
>> means of some other reference/link) of that linked list and want to stride 
>> backward?
> 
> You can’t; if it’s singly-linked then there’s no way to do that directly with 
> the target of O(1) complexity, i.e- for every step backward you’d have to 
> start again from the beginning of the list and step forward till you reach 
> the correct element, which would make it O(n) performance. For this reason, a 
> singly linked list would want to provide only a ForwardIndex, as it isn’t 
> suited to stepping backwards through its elements (that’s what a 
> doubly-linked list is for, at the cost of even more overhead).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-11 Thread Haravikk via swift-evolution

> On 10 Apr 2016, at 22:44, Ted F.A. van Gaalen via swift-evolution 
>  wrote:
> 
>> Say you wanted to stride through a singly-linked list, it would actually be 
>> beneficial to support only forward strides, the same is true of sequences, 
>> as you either may not know what the endpoint is, or would have to step 
>> through the whole sequence to find it (plus buffer every value in order to 
>> do-so safely).
> What if you are already somewhere in the middle (perhaps landed there by 
> means of some other reference/link) of that linked list and want to stride 
> backward? 

You can’t; if it’s singly-linked then there’s no way to do that directly with 
the target of O(1) complexity, i.e- for every step backward you’d have to start 
again from the beginning of the list and step forward till you reach the 
correct element, which would make it O(n) performance. For this reason, a 
singly linked list would want to provide only a ForwardIndex, as it isn’t 
suited to stepping backwards through its elements (that’s what a doubly-linked 
list is for, at the cost of even more overhead).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Jose Cheyo Jimenez via swift-evolution


> On Apr 9, 2016, at 1:27 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Sat, Apr 9, 2016 at 5:44 AM, Wallacy via swift-evolution
>  wrote:
>> Just as note, i think the sintax should be:
>> 
>> 0...9
>> 0..<9
>> 0>..9
>> 0>.<9

I agree with this. 
>> 
>> Because the intention is produce a number bigger than 0 (start). So greater
>> than zero less than nine.
> 
> That's not typically how it's written in math. When x is between two
> values a and b, it's written a < x < b. The pointy end of the symbol
> faces the smaller value. Here, 0 is the smaller value, so the pointy
> end must face it, as in `0 <.. 9` and `0 <.< 9`.

I don't agree with this and I bet this is why Perl uses ^ for that purpose. 

Including these not yet proposed operators will be distracting to the review of 
the proposal. These discussions would be better served as their own proposed 
proposal.  
I recommend removing any mention of them from this proposal.


>> 
>> 
>> 
>> 
>> Em sex, 8 de abr de 2016 22:50, Michel Fortin via swift-evolution
>>  escreveu:
>>> 
>>> Le 8 avr. 2016 à 14:37, Erica Sadun via swift-evolution
>>>  a écrit :
 
 (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
>>> 
>>> The above reads wrong to me. The expression has to be read differently
>>> depending on the tinny detail that is the sign of the step that comes last:
>>> 
>>> * positive step: from 0 to 9 striding by 2
>>> * negative step: to 0 from 9 striding by -2
>>> 
>>> Am I the only one thinking it's a bit too clever to swap the start and
>>> stop parts like this?
>>> 
>>> --
>>> Michel Fortin
>>> https://michelf.ca
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Ted F.A. van Gaalen via swift-evolution
> Say you wanted to stride through a singly-linked list, it would actually be 
> beneficial to support only forward strides, the same is true of sequences, as 
> you either may not know what the endpoint is, or would have to step through 
> the whole sequence to find it (plus buffer every value in order to do-so 
> safely).
What if you are already somewhere in the middle (perhaps landed there by means 
of some other reference/link) of that linked list and want to stride backward? 


>> A consistent behavior with signed distances is so important that we are 
>> currently struggling with an interesting issue with floating point types, 
>> which is that due to rounding error 10.0 + a - a != 10.0 for some values of 
>> a.
Of course ! 
This is known (in computer domain) since ca. 1938.. (Konrad Zuse, with 22-bit 
floats) 
(btw I am glad that computer development in this critical war times especially 
in
nazi-Germany was extremely slow, relatively speaking, just imagine...) 

So, this should come as no surprise. 
Precision loss occurs with all arithmetic operations on floats. 
(in the above case probably the intermediate 
expression evaluation around the  !=  ,  
Compiler optimization may also cause
even further reduction of floating point precision )

Obviously, when working with floating point numbers 
one must always be aware of this and design/program 
accordingly.  This should become second nature.

E.g. it is perfectly acceptable and known (also in classical for-loops) 
that  
(0.0…1.0).by(0.1)
is not guaranteed to reach the humanly expected value of 1.0.

Due to the nature of what mostly is done in the floating point numbers domain, 
this does not often cause problems (e.g like working with a slide ruler) 

if it is important to reach the “expected end” then one could
-add a precision loss compensating value like so 
  (v1…v2 + 0.1) 
-or generate the desired float sequence within an integer loop **

The whole point with stride() here is perhaps because the attempt
to treat Continuous Data (floats)   as   Discrete Data (Integers) ?  

What about range operator?   
   with floats,  (a…b)  will never work correctly(accept this as normal, 
inherent with floats) 

I’d suggest 
(a<.

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Xiaodi Wu via swift-evolution
On Sun, Apr 10, 2016 at 3:58 PM, Haravikk  wrote:
>
> On 10 Apr 2016, at 14:25, Xiaodi Wu  wrote:
>
> What types do you have in mind that would only support positive distances?
> All numeric types (yes, even UInt, etc.) have signed distances, which
> reflects the basic mathematical abstraction of a number line.
>
>
> Say you wanted to stride through a singly-linked list, it would actually be
> beneficial to support only forward strides, the same is true of sequences,
> as you either may not know what the endpoint is, or would have to step
> through the whole sequence to find it (plus buffer every value in order to
> do-so safely).
>
> A consistent behavior with signed distances is so important that we are
> currently struggling with an interesting issue with floating point types,
> which is that due to rounding error 10.0 + a - a != 10.0 for some values of
> a.
>
>
> While that’s interesting I’m not sure why the sign is important; to me a
> stride is a width so it being negative makes no sense. For example, say I
> laid an array of Ints, organised into groups of five (and also that I’m
> lunatic who won’t use a tuple for this), the stride of this array is 5
> whether I’m stepping through it forwards or backwards. Imagine I defined
> this like so (more realistically it’d be a struct or a class):
>
> typealias StridedIntegerArray:(stride:Int, array:[Int])
>
> If the stride is set to 5, it’s always 5, the only thing that changes is
> whether I want to stride from the start or end of the array, plus I could
> things like:
>
> myStridedIntegerArray.prefix(from: 2).striding(forwardBy:
> myStridedIntegerArray.stride) // Returns element at index 2, 7, 12, etc.

When you have a sequence returning elements at index 12, 7, 2, etc.,
wouldn't you call the stride size -5? I would, because 12 + (-5) = 7.

>
>
> It just occurred to me that perhaps you intended this method only for ranges
> specifically and that perhaps I’m confusing things, but it seems to me like
> it should be a method for all sequences (with reverse stride available on
> collections with a reverse index type) returning a generator that only
> returns (or computes) every Nth element, for generic sequences/collections
> this would take the start or end index and use advanced(by:), though again,
> I kind of feel like that should be two separate methods as well, but that’s
> for another issue I think.

I don't think it should be for ranges only, but ranges are the extent
of this proposal.

That said, my own opinion is that striding should not be available on
sequences but on collections only. In their most commonly used form,
integer strides take a start and end, and there is a finite number of
things to stride over; thus, in my reasoning, strides can be extended
to cover anything else that has a known start and end and has a finite
number of things, which is guaranteed by conformance to Collection but
not to Sequence. (At the moment, StrideTo/Through conforms to Sequence
and not to Collection, but that is considered something to be fixed
and we will see if we can address that as part of this set of stride
overhauls.)

As I see it, we agree on the problem: the current algorithm cannot
accommodate singly linked lists and sequences because those things do
not have a known endpoint if you begin an attempt to stride. However,
my conclusion is the opposite of yours: namely, that they should not
have stride. Maybe they should have something similar, but it
shouldn't be stride.

>
> On Sun, Apr 10, 2016 at 12:53 PM Haravikk via swift-evolution
>  wrote:
>>
>>
>> On 10 Apr 2016, at 11:17, Brent Royal-Gordon 
>> wrote:
>>
>> Why not just assign it the correct sign during the init function?
>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by
>>
>>
>> One reason not to do it this way is that, if we extend `striding(by:)` to
>> other collections, they will not be as easy to walk backwards through as
>> this. You will have to do something like
>> `collection.reversed().striding(by:)` which will be a hassle.
>>
>>
>> Any thoughts on the alternative I mentioned a little earlier to define
>> overloads instead of positive/negative? i.e- you would have two methods,
>> .striding(forwardBy:) and .striding(backwardBy:). In addition to eliminating
>> the use of a negative stride to indicate direction, this has the advantage
>> that .striding(backwardBy:) can be defined only for types with a
>> ReverseIndex or only for collections (as you can stride through a sequence,
>> but only by going forward).
>>
>> This should also make documentation a bit clearer, otherwise you’ve got
>> the caveat that to go backwards requires a negative value, but only if the
>> type supports that, which a developer would then need to check. Instead it
>> either has the backwardBy variant or not.
>>
>> I 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Dave Abrahams via swift-evolution

on Sun Apr 10 2016, Michel Fortin  wrote:

> Le 10 avr. 2016 à 6:17, Brent Royal-Gordon via swift-evolution 
>  a écrit :
>
>> Remember, conditional branches are relatively slow, and we want to
> avoid them where we can. If this is, for instance, the test of a loop,
> the extra branch is not a good thing.
>
> Perhaps it's a bit extreme, but my idea for stride is that it should
> only have one branch in the loop condition and absolutely no other
> branch. 

I agree that would be ideal.  When the stride is statically known, I am
confident that the optimizer can eliminate the branch.  When the stride
is not statically known, presumably you need the branch anyway, though
one might have to hope for the optimizer to copy and split the loop
(i.e. create two specializations based on sign).

> The primitive stride could be defined like this:
>
>   stride(from: 0, compare: <, to: 10, by: 2)

Now you're adding a function call in lieu of a branch.  We could easily
build stride so it stores a comparison function based on the sign of the
stride, if we thought this would be better.  Would it?

> and on top you could add some convenience functions for the <, >, <=, and >= 
> cases:
>
>   stride(from: 0, to: 10, by: 2) // stride(from: 0, compare: <, to: 10, 
> by: 2)
>   stride(from: 10, downTo: 0, by: -2) // stride(from: 10, compare: >, to: 
> 0, by -2)
>
>   stride(from: 0, through: 10, by: 2) // stride(from: 10, compare: <=, 
> to: 10, by 2)
>   stride(from: 10, downThrough: 0, by: -2) // stride(from: 10, compare: 
> >=, to: 0, by -2)
>
> None of these should try to prevent you from making an infinite
> sequence, so no trap for `by: 0` or one that moves the value in the
> wrong direction. And certainly no extra loop branch based on the sign
> of the stride (that's the most important part).
>
> Based on that, you could add some convenience for ranges:
>
>   (0 ..< 10).striding(by: 2) // shortcut for: stride(from: 0, to: 10, by 
> 2)
>   (0 ..< 10).stridingDown(by: -2) // shortcut for: stride(from: 10, to: 
> 0, by -2)
>
> I guess in this case it'd be fine to add a precondition to check that
> `by` is not in the reverse direction so we can preserve the semantics
> of iterating over a collection. But because of this precondition and
> the other one in Range, I would actually prefer the non-range forms if
> I was using a `stride` in a nested loop.

-- 
Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Dave Abrahams via swift-evolution

on Sun Apr 10 2016, Brent Royal-Gordon  wrote:

>> I can’t imagine any scenario in which getting the step's sign wrong wouldn’t 
>> just be a typo.
>
> Well, it could be an error if you derive the stride by subtracting two
> numbers, and the second number is unexpectedly larger than the
> first. Of course, that makes it a *bug*, not a typo.
>
>> Why not just assign it the correct sign during the init function?
>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by
>
> One reason not to do it this way is that, if we extend `striding(by:)`
> to other collections, they will not be as easy to walk backwards
> through as this. You will have to do something like
> `collection.reversed().striding(by:)` which will be a hassle.

IMO that is an acceptable result for collections that are not
bidirectional, just as in Swift 2 you can't measure the distance between
two ForwardIndex'es that are in the wrong order.

-- 
Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Haravikk via swift-evolution

> On 10 Apr 2016, at 14:25, Xiaodi Wu  wrote:
> 
> What types do you have in mind that would only support positive distances? 
> All numeric types (yes, even UInt, etc.) have signed distances, which 
> reflects the basic mathematical abstraction of a number line.

Say you wanted to stride through a singly-linked list, it would actually be 
beneficial to support only forward strides, the same is true of sequences, as 
you either may not know what the endpoint is, or would have to step through the 
whole sequence to find it (plus buffer every value in order to do-so safely).

> A consistent behavior with signed distances is so important that we are 
> currently struggling with an interesting issue with floating point types, 
> which is that due to rounding error 10.0 + a - a != 10.0 for some values of a.

While that’s interesting I’m not sure why the sign is important; to me a stride 
is a width so it being negative makes no sense. For example, say I laid an 
array of Ints, organised into groups of five (and also that I’m lunatic who 
won’t use a tuple for this), the stride of this array is 5 whether I’m stepping 
through it forwards or backwards. Imagine I defined this like so (more 
realistically it’d be a struct or a class):

typealias StridedIntegerArray:(stride:Int, array:[Int])

If the stride is set to 5, it’s always 5, the only thing that changes is 
whether I want to stride from the start or end of the array, plus I could 
things like:

myStridedIntegerArray.prefix(from: 2).striding(forwardBy: 
myStridedIntegerArray.stride) // Returns element at index 2, 7, 12, etc.


It just occurred to me that perhaps you intended this method only for ranges 
specifically and that perhaps I’m confusing things, but it seems to me like it 
should be a method for all sequences (with reverse stride available on 
collections with a reverse index type) returning a generator that only returns 
(or computes) every Nth element, for generic sequences/collections this would 
take the start or end index and use advanced(by:), though again, I kind of feel 
like that should be two separate methods as well, but that’s for another issue 
I think.

> On Sun, Apr 10, 2016 at 12:53 PM Haravikk via swift-evolution 
> > wrote:
> 
>> On 10 Apr 2016, at 11:17, Brent Royal-Gordon > > wrote:
>> 
>>> Why not just assign it the correct sign during the init function?
>>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
>>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by
>> 
>> One reason not to do it this way is that, if we extend `striding(by:)` to 
>> other collections, they will not be as easy to walk backwards through as 
>> this. You will have to do something like 
>> `collection.reversed().striding(by:)` which will be a hassle.
> 
> Any thoughts on the alternative I mentioned a little earlier to define 
> overloads instead of positive/negative? i.e- you would have two methods, 
> .striding(forwardBy:) and .striding(backwardBy:). In addition to eliminating 
> the use of a negative stride to indicate direction, this has the advantage 
> that .striding(backwardBy:) can be defined only for types with a ReverseIndex 
> or only for collections (as you can stride through a sequence, but only by 
> going forward).
> 
> This should also make documentation a bit clearer, otherwise you’ve got the 
> caveat that to go backwards requires a negative value, but only if the type 
> supports that, which a developer would then need to check. Instead it either 
> has the backwardBy variant or not.
> 
> I know that advance(by:) supports negative values, but this is actually 
> something I wouldn’t mind seeing changed as well, as it has the same issues 
> (passing a negative value in looks fine until you realise the type is a 
> ForwardIndex only). It would also allow us to define Distance types that 
> don’t support a direction, since this would be given by the choice of method 
> called instead.
> 
> 
> Of course I’d still like to be able to define 6 … 0 or whatever, but this 
> would at least eliminate what I dislike about using negatives for direction.
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Xiaodi Wu via swift-evolution
What types do you have in mind that would only support positive distances?
All numeric types (yes, even UInt, etc.) have signed distances, which
reflects the basic mathematical abstraction of a number line.

A consistent behavior with signed distances is so important that we are
currently struggling with an interesting issue with floating point types,
which is that due to rounding error 10.0 + a - a != 10.0 for some values of
a.

On Sun, Apr 10, 2016 at 12:53 PM Haravikk via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On 10 Apr 2016, at 11:17, Brent Royal-Gordon 
> wrote:
>
> Why not just assign it the correct sign during the init function?
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by
>
>
> One reason not to do it this way is that, if we extend `striding(by:)` to
> other collections, they will not be as easy to walk backwards through as
> this. You will have to do something like
> `collection.reversed().striding(by:)` which will be a hassle.
>
>
> Any thoughts on the alternative I mentioned a little earlier to define
> overloads instead of positive/negative? i.e- you would have two methods,
> .striding(forwardBy:) and .striding(backwardBy:). In addition to
> eliminating the use of a negative stride to indicate direction, this has
> the advantage that .striding(backwardBy:) can be defined only for types
> with a ReverseIndex or only for collections (as you can stride through a
> sequence, but only by going forward).
>
> This should also make documentation a bit clearer, otherwise you’ve got
> the caveat that to go backwards requires a negative value, but only if the
> type supports that, which a developer would then need to check. Instead it
> either has the backwardBy variant or not.
>
> I know that advance(by:) supports negative values, but this is actually
> something I wouldn’t mind seeing changed as well, as it has the same issues
> (passing a negative value in looks fine until you realise the type is a
> ForwardIndex only). It would also allow us to define Distance types that
> don’t support a direction, since this would be given by the choice of
> method called instead.
>
>
> Of course I’d still like to be able to define 6 … 0 or whatever, but this
> would at least eliminate what I dislike about using negatives for direction.
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Michel Fortin via swift-evolution
Le 10 avr. 2016 à 6:17, Brent Royal-Gordon via swift-evolution 
 a écrit :

> Remember, conditional branches are relatively slow, and we want to avoid them 
> where we can. If this is, for instance, the test of a loop, the extra branch 
> is not a good thing.

Perhaps it's a bit extreme, but my idea for stride is that it should only have 
one branch in the loop condition and absolutely no other branch. The primitive 
stride could be defined like this:

stride(from: 0, compare: <, to: 10, by: 2)

and on top you could add some convenience functions for the <, >, <=, and >= 
cases:

stride(from: 0, to: 10, by: 2) // stride(from: 0, compare: <, to: 10, 
by: 2)
stride(from: 10, downTo: 0, by: -2) // stride(from: 10, compare: >, to: 
0, by -2)

stride(from: 0, through: 10, by: 2) // stride(from: 10, compare: <=, 
to: 10, by 2)
stride(from: 10, downThrough: 0, by: -2) // stride(from: 10, compare: 
>=, to: 0, by -2)

None of these should try to prevent you from making an infinite sequence, so no 
trap for `by: 0` or one that moves the value in the wrong direction. And 
certainly no extra loop branch based on the sign of the stride (that's the most 
important part).

Based on that, you could add some convenience for ranges:

(0 ..< 10).striding(by: 2) // shortcut for: stride(from: 0, to: 10, by 
2)
(0 ..< 10).stridingDown(by: -2) // shortcut for: stride(from: 10, to: 
0, by -2)

I guess in this case it'd be fine to add a precondition to check that `by` is 
not in the reverse direction so we can preserve the semantics of iterating over 
a collection. But because of this precondition and the other one in Range, I 
would actually prefer the non-range forms if I was using a `stride` in a nested 
loop.

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Brent Royal-Gordon via swift-evolution
> I can’t imagine any scenario in which getting the step's sign wrong wouldn’t 
> just be a typo.

Well, it could be an error if you derive the stride by subtracting two numbers, 
and the second number is unexpectedly larger than the first. Of course, that 
makes it a *bug*, not a typo.

> Why not just assign it the correct sign during the init function?
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by

One reason not to do it this way is that, if we extend `striding(by:)` to other 
collections, they will not be as easy to walk backwards through as this. You 
will have to do something like `collection.reversed().striding(by:)` which will 
be a hassle.

And the same may apply to Range, for that matter, because…

> (OTOH, I don’t understand why 6…0 is currently a crash, rather than the, 
> IMHO, obviously intended sequence of “6,5,4,3,2,1,0”, so maybe I’m not the 
> best person to ask)

Well, suppose you say `6...0`. There are three ways that could be represented:

1.  Range(start: 0, end: 6)
2.  Range(start: 6, end: 0)
3.  Range(start: 0, end: 6, reversed: true)

Option 1 throws away the fact that the range was ever reversed, so it doesn't 
actually help with this case.

Option 2 complicates testing. Where before you might have written this:

let inBounds = start <= x < end

Now you must write:

let inBounds: Bool
if start < end {
inBounds = start <= x && x < end
}
else {
inBounds = start >= x && x > end
}

Remember, conditional branches are relatively slow, and we want to avoid them 
where we can. If this is, for instance, the test of a loop, the extra branch is 
not a good thing.

Option 3 avoids this issue, but it requires more space. It also requires 
branches in other places which care about order.

And both 2 and 3 complicate slicing. If you say `array[6...0] = newValues`, the 
operation should probably be performed such that `array[6] == newValues[0]`. 
That seems difficult to implement—and all too easy to forget to handle. And I 
can imagine that it might prevent certain optimizations if the compiler 
couldn't prove they were forward ranges.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Brent Royal-Gordon via swift-evolution
> I can’t imagine any scenario in which getting the step's sign wrong wouldn’t 
> just be a typo.

Well, it could be an error if you derive the stride by subtracting two numbers, 
and the second number is unexpectedly larger than the first. Of course, that 
makes it a *bug*, not a typo.

> Why not just assign it the correct sign during the init function?
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by

One reason not to do it this way is that, if we extend `striding(by:)` to other 
collections, they will not be as easy to walk backwards through as this. You 
will have to do something like `collection.reversed().striding(by:)` which will 
be a hassle.

And the same may apply to Range, for that matter, because…

> (OTOH, I don’t understand why 6…0 is currently a crash, rather than the, 
> IMHO, obviously intended sequence of “6,5,4,3,2,1,0”, so maybe I’m not the 
> best person to ask)

Well, suppose you say `6...0`. There are three ways that could be represented:

1.  Range(start: 0, end: 6)
2.  Range(start: 6, end: 0)
3.  Range(start: 0, end: 6, reversed: true)

Option 1 throws away the fact that the range was ever reversed, so it doesn't 
actually help with this case.

Option 2 complicates testing. Where before you might have written this:

let inBounds = start <= x < end

Now you must write:

let inBounds: Bool
if start < end {
inBounds = start <= x && x < end
}
else {
inBounds = start >= x && x > end
}

Remember, conditional branches are relatively slow, and we want to avoid them 
where we can. If this is, for instance, the test of a loop, the extra branch is 
not a good thing.

Option 3 avoids this issue, but it requires more space. It also requires 
branches in other places which care about order.

And both 2 and 3 complicate slicing. If you say `array[6...0] = newValues`, the 
operation should probably be performed such that `array[6] == newValues[0]`. 
That seems difficult to implement—and all too easy to forget to handle. And I 
can imagine that it might prevent certain optimizations if the compiler 
couldn't prove they were forward ranges.

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Xiaodi Wu via swift-evolution
The iteration counter will be floating point and the iterator will break
down after incrementing by one is no longer exactly representable. It has
been made clear on this list that there is a strong preference that no
floating point stride should degenerate into an infinite loop due to this
issue. Thus, there will be a limit at the time a floating point stride is
created of 2^53 steps (in the case of a Double--some thought is necessary
for a Float). As currently mocked up the logic is whether start + 2^53 *
stride gets you to/through the end. If not, precondition failure.
On Sun, Apr 10, 2016 at 7:41 AM  wrote:

> I understand (and agree with) 3/4 of that… Why do we want to prevent
> striding *to* an infinity? I mean, yeah it’ll take a long time to get
> there, but with the new floating point stride code, a floating point value
> will *eventually* “overflow” into infinity (or `iteration += 1` will
> overflow and crash), it’s just that at that point there isn’t a
> straight-forward way to go the other direction anymore.
>
> Actually, striding from an infinity should be ok, too, as long as it’s not
> the actual starting point:
> let x = -Double.infinity ... 0.0 // Big Problems in, um, Non-Little
> Loops… or something… (and apologies to Kurt Russell)
> let x = -Double.infinity <.. 0.0 // starts at `nextafter(start, end)`
> (-1.797693134862316e+308, in this case)
>
> If the infinities are definitely out even as exclusive endpoints, can the
> floating point types get min/max properties like the integer types have?
> let x = Double.min ... Double.max // same as -1.797693134862316e+308 ... 
> 1.797693134862316e+308,
> but way easier to write
> let x = Float.min ... Float.max // same as -3.402823e+38 ... 3.402823e+38
>
> - Dave Sweeris
>
> On Apr 10, 2016, at 12:05 AM, Xiaodi Wu  wrote:
>
> We will be proposing exactly that which you've put in parentheses, i.e.
> floating point types will get their own strides, and it will be a
> precondition failure to try to stride from or to infinity or nan :)
>
> On Sun, Apr 10, 2016 at 4:47 AM  wrote:
>
>> It’s not a matter of floating point error accumulation… At least on my
>> machine, once a Double hits +/-∞, there’s no way that I know of to get back
>> to normal floating point numbers. That is to say, for *all* normal, finite
>> values of x, "-Double.infinity + x" will just return “-inf". If x is to
>> equal Double.infinity, Double.NaN, or Double.quietNaN, then it’ll return
>> “nan” (which, incidentally, will fail the regular equality test… Double.NaN
>> isn’t even equal to itself; I think checking the floating point class is
>> the way to do it).
>>
>> I could easily be missing something, but AFAICT the only way to always
>> get the correct sequence (without splitting the floating point types off
>> into their own thing) is either have a negative stride swap start and end
>> *before* the StrideTo starts generating values (that is, *not* by just
>> calling `.reverse()` on something with a positive stride), or to allow “0
>> ..< -Double.infinity” to be a valid range (with the negative stride being
>> implied).
>>
>> - Dave Sweeris
>>
>> On Apr 9, 2016, at 6:59 PM, Xiaodi Wu  wrote:
>>
>> Yikes. Not too concerned about the infinite loop issue, as floating point
>> strides when fixed to avoid error accumulation will necessarily enforce a
>> finite number of steps. However, you're talking a regular, not-at-all-lazy
>> Array being returned? That would be not good at all...
>>
>> On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> While I’m in favour of the basic idea I think the operator selection is
>>> too complex, and I’m not sure about the need for negative strides. Really
>>> all I want are the following:
>>>
>>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
>>> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
>>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
>>> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>>>
>>> Everything else should be coverable either by flipping the order, or
>>> using .reverse(). The main advantage is that there’s only one new operator
>>> to clarify the 6 ..> 0 case, though you could always just reuse the
>>> existing operator if you just interpret it as “x from 6 to, but not
>>> including, 0"
>>>
>>>
>>> `.reverse()` returns an array, though, not a StrideTo<>, which means
>>> it’ll get in an infinite loop on infinite sequences. This works fine:
>>> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
>>> if someTestInvolving(i) { break }
>>> ...
>>> }
>>>
>>> But this never even starts executing the loop because of the infinite
>>> loop inside `.reverse()`:
>>> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
>>> if 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-10 Thread Dave via swift-evolution
I understand (and agree with) 3/4 of that… Why do we want to prevent striding 
*to* an infinity? I mean, yeah it’ll take a long time to get there, but with 
the new floating point stride code, a floating point value will *eventually* 
“overflow” into infinity (or `iteration += 1` will overflow and crash), it’s 
just that at that point there isn’t a straight-forward way to go the other 
direction anymore.

Actually, striding from an infinity should be ok, too, as long as it’s not the 
actual starting point:
let x = -Double.infinity ... 0.0 // Big Problems in, um, Non-Little Loops… or 
something… (and apologies to Kurt Russell)
let x = -Double.infinity <.. 0.0 // starts at `nextafter(start, end)` 
(-1.797693134862316e+308, in this case)

If the infinities are definitely out even as exclusive endpoints, can the 
floating point types get min/max properties like the integer types have?
let x = Double.min ... Double.max // same as -1.797693134862316e+308 ... 
1.797693134862316e+308, but way easier to write
let x = Float.min ... Float.max // same as -3.402823e+38 ... 3.402823e+38

- Dave Sweeris

> On Apr 10, 2016, at 12:05 AM, Xiaodi Wu  wrote:
> 
> We will be proposing exactly that which you've put in parentheses, i.e. 
> floating point types will get their own strides, and it will be a 
> precondition failure to try to stride from or to infinity or nan :)
> 
> On Sun, Apr 10, 2016 at 4:47 AM  > wrote:
> It’s not a matter of floating point error accumulation… At least on my 
> machine, once a Double hits +/-∞, there’s no way that I know of to get back 
> to normal floating point numbers. That is to say, for *all* normal, finite 
> values of x, "-Double.infinity + x" will just return “-inf". If x is to equal 
> Double.infinity, Double.NaN, or Double.quietNaN, then it’ll return “nan” 
> (which, incidentally, will fail the regular equality test… Double.NaN isn’t 
> even equal to itself; I think checking the floating point class is the way to 
> do it).
> 
> I could easily be missing something, but AFAICT the only way to always get 
> the correct sequence (without splitting the floating point types off into 
> their own thing) is either have a negative stride swap start and end *before* 
> the StrideTo starts generating values (that is, *not* by just calling 
> `.reverse()` on something with a positive stride), or to allow “0 ..< 
> -Double.infinity” to be a valid range (with the negative stride being 
> implied).
> 
> - Dave Sweeris
> 
>> On Apr 9, 2016, at 6:59 PM, Xiaodi Wu > > wrote:
>> 
>> Yikes. Not too concerned about the infinite loop issue, as floating point 
>> strides when fixed to avoid error accumulation will necessarily enforce a 
>> finite number of steps. However, you're talking a regular, not-at-all-lazy 
>> Array being returned? That would be not good at all...
>> 
>> On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution 
>> > wrote:
>> 
>>> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution 
>>> > wrote:
>>> 
>>> While I’m in favour of the basic idea I think the operator selection is too 
>>> complex, and I’m not sure about the need for negative strides. Really all I 
>>> want are the following:
>>> 
>>> (0 ... 6).striding(by: 2)   // [0, 2, 4, 6] x from 0 to 6
>>> (0 ..< 6).striding(by: 2)   // [0, 2, 4]x from 0 while 
>>> <6
>>> (6 ... 0).striding(by: 2)   // [6, 4, 2, 0] x from 6 to 0
>>> (6 ..> 0).striding(by: 2)   // [6, 4, 2]x from 6 while 
>>> >0
>>> 
>>> Everything else should be coverable either by flipping the order, or using 
>>> .reverse(). The main advantage is that there’s only one new operator to 
>>> clarify the 6 ..> 0 case, though you could always just reuse the existing 
>>> operator if you just interpret it as “x from 6 to, but not including, 0"
>> 
>> `.reverse()` returns an array, though, not a StrideTo<>, which means it’ll 
>> get in an infinite loop on infinite sequences. This works fine:
>> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
>> if someTestInvolving(i) { break }
>> ...
>> }
>> 
>> But this never even starts executing the loop because of the infinite loop 
>> inside `.reverse()`:
>> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
>> if someTestInvolving(i) { break }
>> ...
>> }
>> 
>> - Dave Sweeris
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> 

___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
We will be proposing exactly that which you've put in parentheses, i.e.
floating point types will get their own strides, and it will be a
precondition failure to try to stride from or to infinity or nan :)

On Sun, Apr 10, 2016 at 4:47 AM  wrote:

> It’s not a matter of floating point error accumulation… At least on my
> machine, once a Double hits +/-∞, there’s no way that I know of to get back
> to normal floating point numbers. That is to say, for *all* normal, finite
> values of x, "-Double.infinity + x" will just return “-inf". If x is to
> equal Double.infinity, Double.NaN, or Double.quietNaN, then it’ll return
> “nan” (which, incidentally, will fail the regular equality test… Double.NaN
> isn’t even equal to itself; I think checking the floating point class is
> the way to do it).
>
> I could easily be missing something, but AFAICT the only way to always get
> the correct sequence (without splitting the floating point types off into
> their own thing) is either have a negative stride swap start and end
> *before* the StrideTo starts generating values (that is, *not* by just
> calling `.reverse()` on something with a positive stride), or to allow “0
> ..< -Double.infinity” to be a valid range (with the negative stride being
> implied).
>
> - Dave Sweeris
>
> On Apr 9, 2016, at 6:59 PM, Xiaodi Wu  wrote:
>
> Yikes. Not too concerned about the infinite loop issue, as floating point
> strides when fixed to avoid error accumulation will necessarily enforce a
> finite number of steps. However, you're talking a regular, not-at-all-lazy
> Array being returned? That would be not good at all...
>
> On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> While I’m in favour of the basic idea I think the operator selection is
>> too complex, and I’m not sure about the need for negative strides. Really
>> all I want are the following:
>>
>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
>> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
>> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>>
>> Everything else should be coverable either by flipping the order, or
>> using .reverse(). The main advantage is that there’s only one new operator
>> to clarify the 6 ..> 0 case, though you could always just reuse the
>> existing operator if you just interpret it as “x from 6 to, but not
>> including, 0"
>>
>>
>> `.reverse()` returns an array, though, not a StrideTo<>, which means
>> it’ll get in an infinite loop on infinite sequences. This works fine:
>> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
>> if someTestInvolving(i) { break }
>> ...
>> }
>>
>> But this never even starts executing the loop because of the infinite
>> loop inside `.reverse()`:
>> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
>> if someTestInvolving(i) { break }
>> ...
>> }
>>
>> - Dave Sweeris
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Dave via swift-evolution
Oh, right, we’re talking about Swift 3.0… I really need to get that up and 
running on my computer.


> On Apr 9, 2016, at 8:58 PM, Dave Abrahams  wrote:
> 
> 
> on Sat Apr 09 2016, davesweeris-AT-mac.com wrote:
> 
>>On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution
>> wrote:
>> 
>>While I’m in favour of the basic idea I think the operator selection is 
>> too
>>complex, and I’m not sure about the need for negative strides. Really all 
>> I
>>want are the following:
>> 
>>(0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
>>(0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
>>(6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
>>(6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>> 
>>Everything else should be coverable either by flipping the order, or 
>> using .
>>reverse(). The main advantage is that there’s only one new operator to
>>clarify the 6 ..> 0 case, though you could always just reuse the existing
>>operator if you just interpret it as “x from 6 to, but not including, 0"
>> 
>> `.reverse()` returns an array, though, not a StrideTo<>, 
> 
> .reversed() returns a ReversedCollection when the underlying collection
> is bidirectional:
> 
> https://github.com/apple/swift/blob/swift-3-indexing-model/stdlib/public/core/Reverse.swift#L250
> 
> That's lazy and cheap.
> 
>> which means it’ll get in an infinite loop on infinite sequences. 
>> This works fine: for i in stride(from: 0.0, to: Double.infinity, by:
>> M_PI) { if someTestInvolving(i) { break } ...  }
>> 
>> But this never even starts executing the loop because of the infinite loop
>> inside `.reverse()`:
>> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
>> if someTestInvolving(i) { break }
>> ...
>> }
>> 
>> - Dave Sweeris
>> 
> 
> -- 
> Dave

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Dave via swift-evolution
It’s not a matter of floating point error accumulation… At least on my machine, 
once a Double hits +/-∞, there’s no way that I know of to get back to normal 
floating point numbers. That is to say, for *all* normal, finite values of x, 
"-Double.infinity + x" will just return “-inf". If x is to equal 
Double.infinity, Double.NaN, or Double.quietNaN, then it’ll return “nan” 
(which, incidentally, will fail the regular equality test… Double.NaN isn’t 
even equal to itself; I think checking the floating point class is the way to 
do it).

I could easily be missing something, but AFAICT the only way to always get the 
correct sequence (without splitting the floating point types off into their own 
thing) is either have a negative stride swap start and end *before* the 
StrideTo starts generating values (that is, *not* by just calling `.reverse()` 
on something with a positive stride), or to allow “0 ..< -Double.infinity” to 
be a valid range (with the negative stride being implied).

- Dave Sweeris

> On Apr 9, 2016, at 6:59 PM, Xiaodi Wu  wrote:
> 
> Yikes. Not too concerned about the infinite loop issue, as floating point 
> strides when fixed to avoid error accumulation will necessarily enforce a 
> finite number of steps. However, you're talking a regular, not-at-all-lazy 
> Array being returned? That would be not good at all...
> 
> On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution 
> > wrote:
> 
>> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution 
>> > wrote:
>> 
>> While I’m in favour of the basic idea I think the operator selection is too 
>> complex, and I’m not sure about the need for negative strides. Really all I 
>> want are the following:
>> 
>>  (0 ... 6).striding(by: 2)   // [0, 2, 4, 6] x from 0 to 6
>>  (0 ..< 6).striding(by: 2)   // [0, 2, 4]x from 0 while 
>> <6
>>  (6 ... 0).striding(by: 2)   // [6, 4, 2, 0] x from 6 to 0
>>  (6 ..> 0).striding(by: 2)   // [6, 4, 2]x from 6 while 
>> >0
>> 
>> Everything else should be coverable either by flipping the order, or using 
>> .reverse(). The main advantage is that there’s only one new operator to 
>> clarify the 6 ..> 0 case, though you could always just reuse the existing 
>> operator if you just interpret it as “x from 6 to, but not including, 0"
> 
> `.reverse()` returns an array, though, not a StrideTo<>, which means it’ll 
> get in an infinite loop on infinite sequences. This works fine:
> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
> if someTestInvolving(i) { break }
> ...
> }
> 
> But this never even starts executing the loop because of the infinite loop 
> inside `.reverse()`:
> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
> if someTestInvolving(i) { break }
> ...
> }
> 
> - Dave Sweeris
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
Yikes. Not too concerned about the infinite loop issue, as floating point
strides when fixed to avoid error accumulation will necessarily enforce a
finite number of steps. However, you're talking a regular, not-at-all-lazy
Array being returned? That would be not good at all...

On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> While I’m in favour of the basic idea I think the operator selection is
> too complex, and I’m not sure about the need for negative strides. Really
> all I want are the following:
>
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>
> Everything else should be coverable either by flipping the order, or using
> .reverse(). The main advantage is that there’s only one new operator to
> clarify the 6 ..> 0 case, though you could always just reuse the existing
> operator if you just interpret it as “x from 6 to, but not including, 0"
>
>
> `.reverse()` returns an array, though, not a StrideTo<>, which means it’ll
> get in an infinite loop on infinite sequences. This works fine:
> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
> if someTestInvolving(i) { break }
> ...
> }
>
> But this never even starts executing the loop because of the infinite loop
> inside `.reverse()`:
> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
> if someTestInvolving(i) { break }
> ...
> }
>
> - Dave Sweeris
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Dave via swift-evolution
> On Apr 9, 2016, at 5:58 PM, Haravikk via swift-evolution 
>  wrote:
> 
> 
>> On 9 Apr 2016, at 10:50, Xiaodi Wu > > wrote:
>> 
>> But, ranges are useful for more than just stride, and so I would say it 
>> doesn't make sense to have an intrinsic direction for Range, which pointedly 
>> has lowerBound and upperBound but not start and end. For sample, there 
>> shouldn't be (0...9).contains(1) and (9...0).contains(1).
> 
> While I can appreciate that, I wonder if it’s really that important that 0…9 
> and 9…0 are identical? As long as we can be clear on which direction of range 
> we want to generate (so probably still need two new operators), can tell what 
> the direction is, and can convert between them if we need to for some reason 
> (reverse should be fine for that?), then I think we’re okay.
> 
> i.e- 9 … 0 would still cause an error at compile or run-time, we’d have some 
> other operator for doing that, not sure what, plus 9 ..> 0, with both 
> explicitly creating ranges in the reverse direction to avoid mistakes with 
> the order or for computed indices. When it comes down to it the current Range 
> has an implicitly forward direction, so I don’t see the problem with having 
> the same in reverse personally.
> 
> 
> I dunno, at the very least we might want to consider overloading the striding 
> method as .striding(forwardBy:) and .striding(backwardBy:) or something 
> similar, each taking a positive value of some kind to help avoid mistakes in 
> cases where the stride size is computed rather than constant, this would make 
> it more explicit at least.

I can’t imagine any scenario in which getting the step's sign wrong wouldn’t 
just be a typo. Why not just assign it the correct sign during the init 
function?
(0 ... 6).striding(by: 2) // [0, 2, 4, 6], end > start, so stride = by
(6 ... 0).striding(by: 2) // [6, 4, 2, 0], start > end, so stride = -by

(OTOH, I don’t understand why 6…0 is currently a crash, rather than the, IMHO, 
obviously intended sequence of “6,5,4,3,2,1,0”, so maybe I’m not the best 
person to ask)

- Dave Sweeris___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
IMO, 9...0 is a non-starter. Especially with Range taking on the role of
Interval, it's critical that they have no direction. Suppose you have two
ranges, 0...9 and 9...0. Is 0...9 == 9...0? IMO, two countable ranges r0
and r1 are equal if, for value in r0, r1.contains(value) == true, and vice
versa. (Sorry for the pseudocode; I'm typing on a phone.) However, if Range
has intrinsic direction, either equality ignores direction (ludicrous) or
0...9 != 9...0 (unacceptable).

Since we have `reverse()`, all ambiguity could be resolved by prohibiting
negative stride sizes altogether, I suppose. So, (0...9).striding(by:
2).reverse() could be the one Swifty way to stride backwards. Is that
objectionable to people?

On Sat, Apr 9, 2016 at 11:58 PM Haravikk 
wrote:

> On 9 Apr 2016, at 10:50, Xiaodi Wu  wrote:
>
> But, ranges are useful for more than just stride, and so I would say it
> doesn't make sense to have an intrinsic direction for Range, which
> pointedly has lowerBound and upperBound but not start and end. For sample,
> there shouldn't be (0...9).contains(1) and (9...0).contains(1).
>
>
> While I can appreciate that, I wonder if it’s really that important that
> 0…9 and 9…0 are identical? As long as we can be clear on which direction of
> range we want to generate (so probably still need two new operators), can
> tell what the direction is, and can convert between them if we need to for
> some reason (reverse should be fine for that?), then I think we’re okay.
>
> i.e- 9 … 0 would still cause an error at compile or run-time, we’d have
> some other operator for doing that, not sure what, plus 9 ..> 0, with both
> explicitly creating ranges in the reverse direction to avoid mistakes with
> the order or for computed indices. When it comes down to it the current
> Range has an implicitly forward direction, so I don’t see the problem with
> having the same in reverse personally.
>
>
> I dunno, at the very least we might want to consider overloading the
> striding method as .striding(forwardBy:) and .striding(backwardBy:) or
> something similar, each taking a positive value of some kind to help avoid
> mistakes in cases where the stride size is computed rather than constant,
> this would make it more explicit at least.
>
> On Sat, Apr 9, 2016 at 10:33 AM Haravikk 
> wrote:
>
>> While I’m in favour of the basic idea I think the operator selection is
>> too complex, and I’m not sure about the need for negative strides. Really
>> all I want are the following:
>>
>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
>> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
>> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>>
>> Everything else should be coverable either by flipping the order, or
>> using .reverse(). The main advantage is that there’s only one new operator
>> to clarify the 6 ..> 0 case, though you could always just reuse the
>> existing operator if you just interpret it as “x from 6 to, but not
>> including, 0"
>>
>> I dunno, I just don’t think that introducing tons of new operators is
>> going to simplify things, and could lead to way more mistakes in practice;
>> the only mistake above would be putting the indices in the wrong order and
>> accidentally reversing the result.
>>
>> Also, I’m against negative strides; while they could be useful for
>> convenience (avoid the need for .reverse or flipping values) I’m just not
>> sure that it makes sense. To me a stride is a distance, thus absolute, what
>> matters is the direction of the range. Naturally we’d need ranges with a
>> direction, but with collections requiring it to be in a particular order
>> (or ignoring it and flipping where necessary).
>>
>> On 8 Apr 2016, at 19:37, Erica Sadun via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Draft here:
>> https://gist.github.com/erica/a51a981ee0352235204692affa959307  Feedback
>> solicited, both positive and negative.
>> We've also got a related proposal about expanding ranges, which you can
>> look at here (
>> https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9)
>>  but we want to float this one first.
>>
>> Thanks, -- E
>>
>>
>>
>>
>>- Proposal: SE-
>>
>>- Author(s): Xiaodi Wu , Pyry Jahkola
>>, Nate Cook 
>>, Erica Sadun 
>>- Status: TBD
>>- Review manager: TBD
>>
>>
>> 
>> Introduction
>>
>> We propose to introduce a striding(by:) method on the revised 3.0 Range
>>  type.
>>
>> This proposal was discussed on the Swift Evolution list in the Feature
>> proposal: Range operator with step
>> 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Dave via swift-evolution

> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution 
>  wrote:
> 
> While I’m in favour of the basic idea I think the operator selection is too 
> complex, and I’m not sure about the need for negative strides. Really all I 
> want are the following:
> 
>   (0 ... 6).striding(by: 2)   // [0, 2, 4, 6] x from 0 to 6
>   (0 ..< 6).striding(by: 2)   // [0, 2, 4]x from 0 while 
> <6
>   (6 ... 0).striding(by: 2)   // [6, 4, 2, 0] x from 6 to 0
>   (6 ..> 0).striding(by: 2)   // [6, 4, 2]x from 6 while 
> >0
> 
> Everything else should be coverable either by flipping the order, or using 
> .reverse(). The main advantage is that there’s only one new operator to 
> clarify the 6 ..> 0 case, though you could always just reuse the existing 
> operator if you just interpret it as “x from 6 to, but not including, 0"

`.reverse()` returns an array, though, not a StrideTo<>, which means it’ll get 
in an infinite loop on infinite sequences. This works fine:
for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
if someTestInvolving(i) { break }
...
}

But this never even starts executing the loop because of the infinite loop 
inside `.reverse()`:
for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
if someTestInvolving(i) { break }
...
}

- Dave Sweeris___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Haravikk via swift-evolution

> On 9 Apr 2016, at 10:50, Xiaodi Wu  wrote:
> 
> But, ranges are useful for more than just stride, and so I would say it 
> doesn't make sense to have an intrinsic direction for Range, which pointedly 
> has lowerBound and upperBound but not start and end. For sample, there 
> shouldn't be (0...9).contains(1) and (9...0).contains(1).

While I can appreciate that, I wonder if it’s really that important that 0…9 
and 9…0 are identical? As long as we can be clear on which direction of range 
we want to generate (so probably still need two new operators), can tell what 
the direction is, and can convert between them if we need to for some reason 
(reverse should be fine for that?), then I think we’re okay.

i.e- 9 … 0 would still cause an error at compile or run-time, we’d have some 
other operator for doing that, not sure what, plus 9 ..> 0, with both 
explicitly creating ranges in the reverse direction to avoid mistakes with the 
order or for computed indices. When it comes down to it the current Range has 
an implicitly forward direction, so I don’t see the problem with having the 
same in reverse personally.


I dunno, at the very least we might want to consider overloading the striding 
method as .striding(forwardBy:) and .striding(backwardBy:) or something 
similar, each taking a positive value of some kind to help avoid mistakes in 
cases where the stride size is computed rather than constant, this would make 
it more explicit at least.

> On Sat, Apr 9, 2016 at 10:33 AM Haravikk  > wrote:
> While I’m in favour of the basic idea I think the operator selection is too 
> complex, and I’m not sure about the need for negative strides. Really all I 
> want are the following:
> 
>   (0 ... 6).striding(by: 2)   // [0, 2, 4, 6] x from 0 to 6
>   (0 ..< 6).striding(by: 2)   // [0, 2, 4]x from 0 while 
> <6
>   (6 ... 0).striding(by: 2)   // [6, 4, 2, 0] x from 6 to 0
>   (6 ..> 0).striding(by: 2)   // [6, 4, 2]x from 6 while 
> >0
> 
> Everything else should be coverable either by flipping the order, or using 
> .reverse(). The main advantage is that there’s only one new operator to 
> clarify the 6 ..> 0 case, though you could always just reuse the existing 
> operator if you just interpret it as “x from 6 to, but not including, 0"
> 
> I dunno, I just don’t think that introducing tons of new operators is going 
> to simplify things, and could lead to way more mistakes in practice; the only 
> mistake above would be putting the indices in the wrong order and 
> accidentally reversing the result.
> 
> Also, I’m against negative strides; while they could be useful for 
> convenience (avoid the need for .reverse or flipping values) I’m just not 
> sure that it makes sense. To me a stride is a distance, thus absolute, what 
> matters is the direction of the range. Naturally we’d need ranges with a 
> direction, but with collections requiring it to be in a particular order (or 
> ignoring it and flipping where necessary).
> 
> 
>> On 8 Apr 2016, at 19:37, Erica Sadun via swift-evolution 
>> > wrote:
>> 
> 
>> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307 
>>   Feedback 
>> solicited, both positive and negative. 
>> We've also got a related proposal about expanding ranges, which you can look 
>> at here (https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9 
>> )
>>  but we want to float this one first.
>> 
>> Thanks, -- E
>> 
>> 
>> 
>> Proposal: SE- 
>> 
>> Author(s): Xiaodi Wu , Pyry Jahkola 
>> , Nate Cook , 
>> Erica Sadun 
>> Status: TBD
>> Review manager: TBD
>>  
>> Introduction
>> 
>> We propose to introduce a striding(by:) method on the revised 3.0 Range type.
>> 
>> This proposal was discussed on the Swift Evolution list in the Feature 
>> proposal: Range operator with step 
>> 
>>  thread. (Direct link 
>>  
>> to original thread)
>> 
>>  
>> Motivation
>> 
>> Updating Range for Swift 3 offers a window of opportunity to simultaneously 
>> improve strides.
>> 
>> Under current Swift 3 plans, n.stride(to:/through:, by:) will be replaced 
>> with a standalone stride(from:, to:/through:, by:) function. We 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Michel Fortin via swift-evolution
Le 9 avr. 2016 à 13:23, Xiaodi Wu  a écrit :

> The sign of the stride size is already (in the current version of Swift) 
> evaluated in the stride generator/iterator; as written, it is evaluated every 
> time next() is called, but of course that is optimized away when possible.

You're right. I had to check the code before I could believe it. How terrible. 
There's two branches per loop iteration:
https://github.com/apple/swift/blob/swift-2.2-branch/stdlib/public/core/Stride.swift#L136

I know the optimizer is probably going to be good enough to elide the first 
branch in most circumstances... but still, relying on the optimizer doing its 
magic does not seem very wise. It's not like you'll get a warning when that 
branch is not elided.

> What we are proposing adds no additional logic to the loop. I can't see a 
> reason why inserting a line to trap on a negative stride size would show any 
> measurable improvement in performance compared to inserting a line to use 
> upperBound for start and lowerBound for end instead of vice versa when 
> initializing an instance of StrideTo/StrideThrough.

That suggestion was based on consistency more than performance. The first part 
of my last email was *not* about performance. I was saying that semantically it 
would make more sense to me if it did the same thing as zero. "I think to be 
consistent it should trap, like with a step of zero, because you can't go from 
0 to 9 with a negative step." I guess we can agree to disagree on this.

Performance-wise, it would actually be one less branch at the start of the loop 
since you can fold it with the zero case using `predcondition(stride > 0)`. And 
I now realize that it'd make it possible to eliminate that dubious extra branch 
in `next()`, so that's one giant reason to do it.

I guess my main issue with `stride` as it is today is that it tries to be 
clever in the edge cases instead of just giving you an infinite sequence. 
Reversing the start and stop boundaries when the step is negative is just a way 
of making it even more clever. So perhaps it fits with the current direction, 
but it does not suit me.

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
The sign of the stride size is already (in the current version of Swift)
evaluated in the stride generator/iterator; as written, it is evaluated
every time next() is called, but of course that is optimized away when
possible. What we are proposing adds no additional logic to the loop. I
can't see a reason why inserting a line to trap on a negative stride size
would show any measurable improvement in performance compared to inserting
a line to use upperBound for start and lowerBound for end instead of vice
versa when initializing an instance of StrideTo/StrideThrough. This would
not be a branch in StrideToIterator.next(), nor even in
StrideToIterator.init(), but rather in StrideTo.init() or even
striding(by:). Rest assured that degrading performance for the most common
use case would be unacceptable (at least to me).

It is already the case that your code needs to account for the sign of the
stride size. Currently, not doing so runs the risk of unintentionally
creating an empty sequence. In our proposal, the result of using a stride
size of unintended sign would differ but the fact that you need to account
for it is unchanged. We are not proposing trapping on negative stride sizes
nor allowing ranges such as 9...0.
On Sat, Apr 9, 2016 at 4:53 PM Michel Fortin 
wrote:

> Le 9 avr. 2016 à 4:25, Xiaodi Wu  a écrit :
> > Note that it's not possible to write 9...0. Once that is clear, it's
> > fairly intuitive (IMO) to look to the stride size for indicating the
> > direction in which we stride, since that is the only other value there
> > is.
>
> I know it's not possible to write 9...0. But I disagree that it's
> intuitive that a negative step value would reverse the start and stop
> values. I think to be consistent it should trap, like with a step of zero,
> because you can't go from 0 to 9 with a negative step.
>
> It's especially important to realize that if the step value is a variable
> you will not be able to know which is the start value and which is the stop
> criterion by quickly inspecting the code because the sign of the step is
> hidden away in the value of that variable.
>
> In other words, whether the loop begins at the start or the end of the
> range becomes a runtime decision. There is a branch in the generator that
> swaps the start and end values depending on that sign. If the step value is
> not a literal constant, inlining might not be able to elide that branch.
> Add another branch to make it trap when given a step of zero. And if it
> traps when the range is invalid (such as in 9...0) then that's another
> branch to check this when you form the range. That's 3 branches needed
> before even starting the loop.
>
> Perhaps I'm just complaining about loosing the good performance
> characteristics of a C-style for loop. In the debate about this it was
> stated many times that `stride` could be used and would have the same
> performance. Is that promise about to be broken now?
>
> On a final note: it's common, for me at least, to enter a loop with the
> start position already higher than the stop criterion, essentially doing
> something like `stride(from: 10, to 5, by 1)` which results in the loop
> being skipped. Translated into this new syntax, it'd become something like
> `(10...5).striding(by: 1)` which of course will trap because of the invalid
> range, thus necessitating an extra `if` to check for this. That clutters
> the code and adds even more branches. Perhaps the solution to this is to
> not trap on ranges with a negative length, although that's probably going
> to cause other headaches elsewhere.
>
> --
> Michel Fortin
> https://michelf.ca
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Michel Fortin via swift-evolution
Le 9 avr. 2016 à 4:25, Xiaodi Wu  a écrit :
> Note that it's not possible to write 9...0. Once that is clear, it's
> fairly intuitive (IMO) to look to the stride size for indicating the
> direction in which we stride, since that is the only other value there
> is.

I know it's not possible to write 9...0. But I disagree that it's intuitive 
that a negative step value would reverse the start and stop values. I think to 
be consistent it should trap, like with a step of zero, because you can't go 
from 0 to 9 with a negative step.

It's especially important to realize that if the step value is a variable you 
will not be able to know which is the start value and which is the stop 
criterion by quickly inspecting the code because the sign of the step is hidden 
away in the value of that variable.

In other words, whether the loop begins at the start or the end of the range 
becomes a runtime decision. There is a branch in the generator that swaps the 
start and end values depending on that sign. If the step value is not a literal 
constant, inlining might not be able to elide that branch. Add another branch 
to make it trap when given a step of zero. And if it traps when the range is 
invalid (such as in 9...0) then that's another branch to check this when you 
form the range. That's 3 branches needed before even starting the loop.

Perhaps I'm just complaining about loosing the good performance characteristics 
of a C-style for loop. In the debate about this it was stated many times that 
`stride` could be used and would have the same performance. Is that promise 
about to be broken now?

On a final note: it's common, for me at least, to enter a loop with the start 
position already higher than the stop criterion, essentially doing something 
like `stride(from: 10, to 5, by 1)` which results in the loop being skipped. 
Translated into this new syntax, it'd become something like 
`(10...5).striding(by: 1)` which of course will trap because of the invalid 
range, thus necessitating an extra `if` to check for this. That clutters the 
code and adds even more branches. Perhaps the solution to this is to not trap 
on ranges with a negative length, although that's probably going to cause other 
headaches elsewhere.

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
Indeed. It's noted under "design concerns" and, IMO, raises the bar for
their addition.

On Sat, Apr 9, 2016 at 12:05 PM Ben Rimmington via swift-evolution <
swift-evolution@swift.org> wrote:

> Re: "Completing the Swift 3 range operator suite"
> 
>
> The proposed operators (<.. and <.<) are not allowed by Swift 2.2 lexer
> grammar:
>
> <
> https://github.com/apple/swift/commit/0bfacde2420937bfb6e0e1be6567b0e90ee2fb67
> >
> <
> https://github.com/apple/swift/commit/d0256a50d0346f7d4b4c00540734febc6bb1
> >
>
> -- Ben
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Ben Rimmington via swift-evolution
Re: "Completing the Swift 3 range operator suite"


The proposed operators (<.. and <.<) are not allowed by Swift 2.2 lexer grammar:




-- Ben

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
I agree with 90% of your comment.

But, ranges are useful for more than just stride, and so I would say it
doesn't make sense to have an intrinsic direction for Range, which
pointedly has lowerBound and upperBound but not start and end. For sample,
there shouldn't be (0...9).contains(1) and (9...0).contains(1).

It's the *traversal* of the range by a stride that has a direction, and
thus the direction should be specified for a particular stride.

Similarly, the rationale for completing the range operators is for the uses
of range that include but are not limited to just stride. If it were just
for stride, then four range operators is three too many.
On Sat, Apr 9, 2016 at 10:33 AM Haravikk 
wrote:

> While I’m in favour of the basic idea I think the operator selection is
> too complex, and I’m not sure about the need for negative strides. Really
> all I want are the following:
>
> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>
> Everything else should be coverable either by flipping the order, or using
> .reverse(). The main advantage is that there’s only one new operator to
> clarify the 6 ..> 0 case, though you could always just reuse the existing
> operator if you just interpret it as “x from 6 to, but not including, 0"
>
> I dunno, I just don’t think that introducing tons of new operators is
> going to simplify things, and could lead to way more mistakes in practice;
> the only mistake above would be putting the indices in the wrong order and
> accidentally reversing the result.
>
> Also, I’m against negative strides; while they could be useful for
> convenience (avoid the need for .reverse or flipping values) I’m just not
> sure that it makes sense. To me a stride is a distance, thus absolute, what
> matters is the direction of the range. Naturally we’d need ranges with a
> direction, but with collections requiring it to be in a particular order
> (or ignoring it and flipping where necessary).
>
> On 8 Apr 2016, at 19:37, Erica Sadun via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307  
> Feedback
> solicited, both positive and negative.
> We've also got a related proposal about expanding ranges, which you can
> look at here (
> https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9)
>  but we want to float this one first.
>
> Thanks, -- E
>
>
>
>
>- Proposal: SE-
>
>- Author(s): Xiaodi Wu , Pyry Jahkola
>, Nate Cook 
>, Erica Sadun 
>- Status: TBD
>- Review manager: TBD
>
>
> 
> Introduction
>
> We propose to introduce a striding(by:) method on the revised 3.0 Range
>  type.
>
> This proposal was discussed on the Swift Evolution list in the Feature
> proposal: Range operator with step
> 
>  thread.
> (Direct link
>  to
> original thread)
> 
> Motivation
>
> Updating Range for Swift 3 offers a window of opportunity to
> simultaneously improve strides.
>
>-
>
>Under current Swift 3 plans, n.stride(to:/through:, by:) will be
>replaced with a standalone stride(from:, to:/through:, by:) function.
>We propose to replace this change with a method on ranges. Using a method
>reduces overall API surface area compared to free functions.
>-
>
>In its current incarnation, the standalone stride function uses
>confusing semantics. The current to implementation returns values in
>*[start, end)* and will never reach or get *to* end. The current
>through implementation returns values in *[start, end]*. It may never
>reach end and certainly never goes *through* that value. Our proposed
>method introduces simple, expected semantics that can be extended to both
>countable and continuous ranges, and to open and closed intervals (both
>half-open and fully-open).
>
>
> Detail
> Design
>
> The striding(by:) method is called on ranges. When used with a positive
> step size, the count starts from the lower bound. With a negative step
> size, the count starts from the upper bound. These bounds apply regardless
> of whether they are inclusive or exclusive.
>
> The following examples should cover all corner cases and include possible
> cases should 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Haravikk via swift-evolution
While I’m in favour of the basic idea I think the operator selection is too 
complex, and I’m not sure about the need for negative strides. Really all I 
want are the following:

(0 ... 6).striding(by: 2)   // [0, 2, 4, 6] x from 0 to 6
(0 ..< 6).striding(by: 2)   // [0, 2, 4]x from 0 while 
<6
(6 ... 0).striding(by: 2)   // [6, 4, 2, 0] x from 6 to 0
(6 ..> 0).striding(by: 2)   // [6, 4, 2]x from 6 while 
>0

Everything else should be coverable either by flipping the order, or using 
.reverse(). The main advantage is that there’s only one new operator to clarify 
the 6 ..> 0 case, though you could always just reuse the existing operator if 
you just interpret it as “x from 6 to, but not including, 0"

I dunno, I just don’t think that introducing tons of new operators is going to 
simplify things, and could lead to way more mistakes in practice; the only 
mistake above would be putting the indices in the wrong order and accidentally 
reversing the result.

Also, I’m against negative strides; while they could be useful for convenience 
(avoid the need for .reverse or flipping values) I’m just not sure that it 
makes sense. To me a stride is a distance, thus absolute, what matters is the 
direction of the range. Naturally we’d need ranges with a direction, but with 
collections requiring it to be in a particular order (or ignoring it and 
flipping where necessary).

> On 8 Apr 2016, at 19:37, Erica Sadun via swift-evolution 
>  wrote:
> 
> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307 
>   Feedback 
> solicited, both positive and negative. 
> We've also got a related proposal about expanding ranges, which you can look 
> at here (https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9 
> )
>  but we want to float this one first.
> 
> Thanks, -- E
> 
> 
> 
> Proposal: SE- 
> 
> Author(s): Xiaodi Wu , Pyry Jahkola 
> , Nate Cook , Erica 
> Sadun 
> Status: TBD
> Review manager: TBD
>  
> Introduction
> 
> We propose to introduce a striding(by:) method on the revised 3.0 Range type.
> 
> This proposal was discussed on the Swift Evolution list in the Feature 
> proposal: Range operator with step 
> 
>  thread. (Direct link 
>  
> to original thread)
> 
>  
> Motivation
> 
> Updating Range for Swift 3 offers a window of opportunity to simultaneously 
> improve strides.
> 
> Under current Swift 3 plans, n.stride(to:/through:, by:) will be replaced 
> with a standalone stride(from:, to:/through:, by:) function. We propose to 
> replace this change with a method on ranges. Using a method reduces overall 
> API surface area compared to free functions.
> 
> In its current incarnation, the standalone stride function uses confusing 
> semantics. The current to implementation returns values in [start, end) and 
> will never reach or get to end. The current through implementation returns 
> values in [start, end]. It may never reach end and certainly never goes 
> through that value. Our proposed method introduces simple, expected semantics 
> that can be extended to both countable and continuous ranges, and to open and 
> closed intervals (both half-open and fully-open).
> 
>  
> Detail
>  Design
> 
> The striding(by:) method is called on ranges. When used with a positive step 
> size, the count starts from the lower bound. With a negative step size, the 
> count starts from the upper bound. These bounds apply regardless of whether 
> they are inclusive or exclusive. 
> 
> The following examples should cover all corner cases and include possible 
> cases should Swift 3 introduce a full complement of open and closed ranges. 
> The syntax for non-canonical range types is not fixed and can be discussed 
> under separate cover.
> 
> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
> (0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]
> 
> (0 ... 9).striding(by: 3) == [0, 3, 6, 9]
> (0 ..< 9).striding(by: 3) == [0, 3, 6]
> (0 <.. 9).striding(by: 3) ==[3, 6, 9]
> (0 <.< 9).striding(by: 3) ==[3, 6]
> 
> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
> (0 ..< 

Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
On Sat, Apr 9, 2016 at 5:44 AM, Wallacy via swift-evolution
 wrote:
> Just as note, i think the sintax should be:
>
> 0...9
> 0..<9
> 0>..9
> 0>.<9
>
> Because the intention is produce a number bigger than 0 (start). So greater
> than zero less than nine.

That's not typically how it's written in math. When x is between two
values a and b, it's written a < x < b. The pointy end of the symbol
faces the smaller value. Here, 0 is the smaller value, so the pointy
end must face it, as in `0 <.. 9` and `0 <.< 9`.

>
>
>
>
> Em sex, 8 de abr de 2016 22:50, Michel Fortin via swift-evolution
>  escreveu:
>>
>> Le 8 avr. 2016 à 14:37, Erica Sadun via swift-evolution
>>  a écrit :
>> >
>> > (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
>>
>> The above reads wrong to me. The expression has to be read differently
>> depending on the tinny detail that is the sign of the step that comes last:
>>
>> * positive step: from 0 to 9 striding by 2
>> * negative step: to 0 from 9 striding by -2
>>
>> Am I the only one thinking it's a bit too clever to swap the start and
>> stop parts like this?
>>
>> --
>> Michel Fortin
>> https://michelf.ca
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
On Sat, Apr 9, 2016 at 2:49 AM, Michel Fortin  wrote:
> Le 8 avr. 2016 à 14:37, Erica Sadun via swift-evolution 
>  a écrit :
>>
>> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
>
> The above reads wrong to me. The expression has to be read differently 
> depending on the tinny detail that is the sign of the step that comes last:
>
> * positive step: from 0 to 9 striding by 2
> * negative step: to 0 from 9 striding by -2
>
> Am I the only one thinking it's a bit too clever to swap the start and stop 
> parts like this?

The issue here is that ranges both do and don't have a direction.
0...9 is supposed to represent all numbers between and including 0 and
9 (agnostic of direction). However, when you have `for i in 0...9 {
code }`, the sequence very much goes from 0 through 9 and not the
other way round.

Note that it's not possible to write 9...0. Once that is clear, it's
fairly intuitive (IMO) to look to the stride size for indicating the
direction in which we stride, since that is the only other value there
is. Thus, we propose using a negative stride size means stride
backwards through the range.

>
> --
> Michel Fortin
> https://michelf.ca
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-09 Thread Xiaodi Wu via swift-evolution
On Sat, Apr 9, 2016 at 1:00 AM, Brent Royal-Gordon
 wrote:
>> We propose to introduce a striding(by:) method on the revised 3.0 Range type.
>
> I take it that we're taking an incremental approach here,

Yes, other proposals are on their way to complement this one.

> and further steps like:
>
> * Adding new range operators

There's a draft proposal being worked on here:
https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9
We're still working on text to give more details on how to implement,
stronger use cases, etc.

> * Making all collections Strideable

This merits additional discussion as to what it means to stride.

> * Unifying Range and IntervalType so we can stride over non-integers again

This would be Dave A's work, which is nearing completion but hasn't
yet been reviewed. You can inspect the ongoing work in the
swift-3-indexing-model branch.

> * Correctly striding over floats

Conflicting opinions exist as to whether to roll that into this
proposal or to write a separate one on that topic.

> Are out of scope for this particular proposal.
>
>> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
>> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
>> (0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
>> (0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]
>
> I favor `stride(over: 0...9, by: 2)`—or perhaps even `Stride(over: 0...9, by: 
> 2)`, where `Stride` is a replacement for `StrideTo` and `StrideThrough`—over 
> a `striding(by:)` method.  The precedence of the range-construction operators 
> makes calling methods on a Range unusually difficult and ugly. (And I don't 
> think adjusting the precedence is a realistic option; that would break things 
> like `0.. issue.

This is an interesting suggestion. One argument for abandoning the
stride(from:to:by:) notation was that what "to" or "through" meant
could be misconstrued. This neatly solves that issue. There is still a
preference for methods over free functions, though.

>> To reverse a stride, call reverse() on the results:
>>
>> (0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]
>
> Does this have different behavior from `(0...9).striding(by: -2)`? (I know it 
> probably has a different implementation.)

It does. We propose `(0...9).striding(by: -2) == [9, 7, 5, 3, 1]`.

>
> --
> Brent Royal-Gordon
> Architechies
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-08 Thread Wallacy via swift-evolution
Just as note, i think the sintax should be:

0...9
0..<9
0>..9
0>.<9

Because the intention is produce a number bigger than 0 (start). So greater
than zero less than nine.



Em sex, 8 de abr de 2016 22:50, Michel Fortin via swift-evolution <
swift-evolution@swift.org> escreveu:

> Le 8 avr. 2016 à 14:37, Erica Sadun via swift-evolution <
> swift-evolution@swift.org> a écrit :
> >
> > (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
>
> The above reads wrong to me. The expression has to be read differently
> depending on the tinny detail that is the sign of the step that comes last:
>
> * positive step: from 0 to 9 striding by 2
> * negative step: to 0 from 9 striding by -2
>
> Am I the only one thinking it's a bit too clever to swap the start and
> stop parts like this?
>
> --
> Michel Fortin
> https://michelf.ca
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-08 Thread Michel Fortin via swift-evolution
Le 8 avr. 2016 à 14:37, Erica Sadun via swift-evolution 
 a écrit :
> 
> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]

The above reads wrong to me. The expression has to be read differently 
depending on the tinny detail that is the sign of the step that comes last:

* positive step: from 0 to 9 striding by 2
* negative step: to 0 from 9 striding by -2

Am I the only one thinking it's a bit too clever to swap the start and stop 
parts like this?

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-08 Thread Brent Royal-Gordon via swift-evolution
> We propose to introduce a striding(by:) method on the revised 3.0 Range type.

I take it that we're taking an incremental approach here, and further steps 
like:

* Adding new range operators
* Making all collections Strideable
* Unifying Range and IntervalType so we can stride over non-integers again
* Correctly striding over floats

Are out of scope for this particular proposal.

> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
> (0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]

I favor `stride(over: 0...9, by: 2)`—or perhaps even `Stride(over: 0...9, by: 
2)`, where `Stride` is a replacement for `StrideTo` and `StrideThrough`—over a 
`striding(by:)` method.  The precedence of the range-construction operators 
makes calling methods on a Range unusually difficult and ugly. (And I don't 
think adjusting the precedence is a realistic option; that would break things 
like `0.. To reverse a stride, call reverse() on the results:
> 
> (0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]

Does this have different behavior from `(0...9).striding(by: -2)`? (I know it 
probably has a different implementation.)

-- 
Brent Royal-Gordon
Architechies

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

2016-04-08 Thread Taras Zakharko via swift-evolution
I am agnostic on a .striding() method, but I am strongly agains any suggestions 
of removing/replacing the global stride() function. The stride function does 
not pollute the global namespace as it is a universally useful construct (among 
others, for implementing classical iterating for loops), has its history in 
contemporary programming (comparable functions in languages like Python, R), 
and is IMO more readable and clear than a range with a striding method method. 
Furthermore, a stride is not a range — its a special sequence, while for ranges 
other rules apply. All in all, I don’t see why stride() and .striding() can’t 
coexist. 

— Taras 

P.S. As a side note, I would prefer if the stride() function be renamed 
sequence() or seq(), but thats just cosmetic personal preference. 


> On 08 Apr 2016, at 20:37, Erica Sadun via swift-evolution 
>  wrote:
> 
> Draft here: https://gist.github.com/erica/a51a981ee0352235204692affa959307 
>   Feedback 
> solicited, both positive and negative. 
> We've also got a related proposal about expanding ranges, which you can look 
> at here (https://gist.github.com/erica/af92c541a0fb69fce1b7aaf8374a5aa9 
> )
>  but we want to float this one first.
> 
> Thanks, -- E
> 
> 
> 
> Proposal: SE- 
> 
> Author(s): Xiaodi Wu , Pyry Jahkola 
> , Nate Cook , Erica 
> Sadun 
> Status: TBD
> Review manager: TBD
>  
> Introduction
> 
> We propose to introduce a striding(by:) method on the revised 3.0 Range type.
> 
> This proposal was discussed on the Swift Evolution list in the Feature 
> proposal: Range operator with step 
> 
>  thread. (Direct link 
>  
> to original thread)
> 
>  
> Motivation
> 
> Updating Range for Swift 3 offers a window of opportunity to simultaneously 
> improve strides.
> 
> Under current Swift 3 plans, n.stride(to:/through:, by:) will be replaced 
> with a standalone stride(from:, to:/through:, by:) function. We propose to 
> replace this change with a method on ranges. Using a method reduces overall 
> API surface area compared to free functions.
> 
> In its current incarnation, the standalone stride function uses confusing 
> semantics. The current to implementation returns values in [start, end) and 
> will never reach or get to end. The current through implementation returns 
> values in [start, end]. It may never reach end and certainly never goes 
> through that value. Our proposed method introduces simple, expected semantics 
> that can be extended to both countable and continuous ranges, and to open and 
> closed intervals (both half-open and fully-open).
> 
>  
> Detail
>  Design
> 
> The striding(by:) method is called on ranges. When used with a positive step 
> size, the count starts from the lower bound. With a negative step size, the 
> count starts from the upper bound. These bounds apply regardless of whether 
> they are inclusive or exclusive. 
> 
> The following examples should cover all corner cases and include possible 
> cases should Swift 3 introduce a full complement of open and closed ranges. 
> The syntax for non-canonical range types is not fixed and can be discussed 
> under separate cover.
> 
> (0 ... 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 ..< 9).striding(by: 2) == [0, 2, 4, 6, 8]
> (0 <.. 9).striding(by: 2) ==[2, 4, 6, 8]
> (0 <.< 9).striding(by: 2) ==[2, 4, 6, 8]
> 
> (0 ... 9).striding(by: 3) == [0, 3, 6, 9]
> (0 ..< 9).striding(by: 3) == [0, 3, 6]
> (0 <.. 9).striding(by: 3) ==[3, 6, 9]
> (0 <.< 9).striding(by: 3) ==[3, 6]
> 
> (0 ... 9).striding(by: -2) == [9, 7, 5, 3, 1]
> (0 ..< 9).striding(by: -2) ==[7, 5, 3, 1]
> (0 <.. 9).striding(by: -2) == [9, 7, 5, 3, 1]
> (0 <.< 9).striding(by: -2) ==[7, 5, 3, 1]
> 
> (0 ... 9).striding(by: -3) == [9, 6, 3, 0]
> (0 ..< 9).striding(by: -3) ==[6, 3, 0]
> (0 <.. 9).striding(by: -3) == [9, 6, 3]
> (0 <.< 9).striding(by: -3) ==[6, 3]
> To reverse a stride, call reverse() on the results:
> 
> (0 ... 9).striding(by: 2).reverse() == [8, 6, 4, 2, 0]
> We note that striding by 0 should be always be a precondition failure.
> 
>  
> Alternatives
>  Considered
> 
> During the on-list discussion, we considered various scenarios