Feature proposal: Range operator with step


(David Knothe) #1

Hi,

I am new to Swift mailing list so I don’t know if this topic has already been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a specified step. Currently, if you would want to iterate over some odd numbers, you had to write:
for i in 1.stride(through: 7, by: 2) { … }
What I think would be simpler and more convenient would be something like the following:
for i in 1 … 7 step 2 { … } . Another option would be for i in 1 … 7; 2 { … }
The keyword ‚step‘ in this context clearly corresponds to the step of the range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges with a step ≠ 1. What do you think?


(Haravikk) #2

I’m behind the idea in principle, but I’m not so sure we need a new keyword for this:

  for eachIndex in (1 ..< 10).by(2) { … }

The above would be adequate I thin, and just requires a new method on ranges and similar types. This is being discussed, among other things, in the c-style for loop discussion, as these were recently removed but without a replacement for this type of use-case.

···

On 23 Mar 2016, at 21:40, David Knothe via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

I am new to Swift mailing list so I don’t know if this topic has already been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a specified step. Currently, if you would want to iterate over some odd numbers, you had to write:
for i in 1.stride(through: 7, by: 2) { … }
What I think would be simpler and more convenient would be something like the following:
for i in 1 … 7 step 2 { … } . Another option would be for i in 1 … 7; 2 { … }
The keyword ‚step‘ in this context clearly corresponds to the step of the range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges with a step ≠ 1. What do you think?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #3

So, in other words, you'd be satisfied with the following addition to
the standard library?

extension Range where Element: Strideable {
    func by(step: Element.Stride) -> StrideTo<Element> {
        return startIndex.stride(to: endIndex, by: step)
    }
}

/*
example of usage:

for i in (1..<10).by(2) {
    print(i)
}
*/
···

On Wed, Mar 23, 2016 at 6:02 PM, Haravikk via swift-evolution <swift-evolution@swift.org> wrote:

I’m behind the idea in principle, but I’m not so sure we need a new keyword
for this:

for eachIndex in (1 ..< 10).by(2) { … }

The above would be adequate I thin, and just requires a new method on ranges
and similar types. This is being discussed, among other things, in the
c-style for loop discussion, as these were recently removed but without a
replacement for this type of use-case.

On 23 Mar 2016, at 21:40, David Knothe via swift-evolution > <swift-evolution@swift.org> wrote:

Hi,

I am new to Swift mailing list so I don’t know if this topic has already
been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a
specified step. Currently, if you would want to iterate over some odd
numbers, you had to write:
for i in 1.stride(through: 7, by: 2) { … }
What I think would be simpler and more convenient would be something like
the following:
for i in 1 … 7 step 2 { … } . Another option would be for i in 1 … 7; 2 { …
}
The keyword ‚step‘ in this context clearly corresponds to the step of the
range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges
with a step ≠ 1. What do you think?
_______________________________________________
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


(David Knothe) #4

I see your point that a simple extension on ranges and similar types would also do the thing.

But I do think that this is not as easy as many users would expect.
For example, I try to avoid parentheses in for loops as much as I can, but in your example, 4 additional brackets are required. A simple keyword („step" or „by“) would solve the problem seamlessly.

Also, a new template could be introduced that shows the existence of the new keyword:

I think adding such a new keyword would improve the ease and the clearness of the Swift language more than just adding some protocol extensions.

···

Am 24.03.2016 um 00:02 schrieb Haravikk <swift-evolution@haravikk.me>:

I’m behind the idea in principle, but I’m not so sure we need a new keyword for this:

  for eachIndex in (1 ..< 10).by(2) { … }

The above would be adequate I thin, and just requires a new method on ranges and similar types. This is being discussed, among other things, in the c-style for loop discussion, as these were recently removed but without a replacement for this type of use-case.

On 23 Mar 2016, at 21:40, David Knothe via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi,

I am new to Swift mailing list so I don’t know if this topic has already been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a specified step. Currently, if you would want to iterate over some odd numbers, you had to write:
for i in 1.stride(through: 7, by: 2) { … }
What I think would be simpler and more convenient would be something like the following:
for i in 1 … 7 step 2 { … } . Another option would be for i in 1 … 7; 2 { … }
The keyword ‚step‘ in this context clearly corresponds to the step of the range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges with a step ≠ 1. What do you think?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #5

My current thinking is that:

* `for x in 0.0..<3.0 {}` should probably be an error, because 1.0 is
  not the obviously-right stride to use for non-integral numbers. That
  would imply that floating types should not conform to Strideable,
  which raises the question of whether Strideable should be folded into
  the Integer protocol.
  
* `for x in (0.0..<20.0).striding(by: 1.3) {}` should work without
  accumulating error

* `for x in 0..<3 {}` should work (obviously; that's the status quo)

* `for x in (0..<20).striding(by: 2)` should work

I think this might also handle the concerns that
https://github.com/apple/swift-evolution/blob/master/proposals/0051-stride-semantics.md
was trying to address.

If I thought extreme concision was important for this application, I'd be
proposing something like

  for x in 0.0..<20.0//1.3 {}

but personally, I don't, which is why I propose `.striding(by: x)`
rather than simply `.by(x)`, the latter being more open to
misinterpretation.

···

on Wed Mar 23 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

So, in other words, you'd be satisfied with the following addition to
the standard library?

extension Range where Element: Strideable {
    func by(step: Element.Stride) -> StrideTo<Element> {
        return startIndex.stride(to: endIndex, by: step)
    }
}

/*
example of usage:

for i in (1..<10).by(2) {
    print(i)
}
*/

--
Dave


(Xiaodi Wu) #6

If it's parentheses you want to avoid, you don't need a keyword to do that.
For example, I can make a stride operator `..+` in four lines like so:

infix operator ..+ { associativity left precedence 134 }
func ..+ <Element: Strideable>(left: Range<Element>, right: Element.Stride)
-> StrideTo<Element> {
    return left.startIndex.stride(to: left.endIndex, by: right)
}

// example of usage:
for i in 1..<10..+2 {
    print(i)
}

The point is, an extension on Range or a custom operator can be constrained
so that Element conforms to Strideable. By contrast, for loops are used to
traverse much more than just ranges. How do you envision your proposed
keyword to interact with everything else? What if I had `var s: Set<Int>`
and tried to write `for i in s by 2`--what do you think should happen? If
you wish to limit `by` to ranges only, what is it about this particular
function that makes it appropriate for a keyword of its own? You will need
more to demonstrate how your proposal achieves what you claim, which is
"improved ease and clearness."

···

On Thu, Mar 24, 2016 at 2:34 AM, David Knothe via swift-evolution < swift-evolution@swift.org> wrote:

I see your point that a simple extension on ranges and similar types would
also do the thing.

But I do think that this is not as easy as many users would expect.
For example, I try to avoid parentheses in for loops as much as I can, but
in your example, 4 additional brackets are required. A simple keyword
(„step" or „by“) would solve the problem seamlessly.

Also, a new template could be introduced that shows the existence of the
new keyword:

I think adding such a new keyword would improve the ease and the clearness
of the Swift language more than just adding some protocol extensions.

Am 24.03.2016 um 00:02 schrieb Haravikk <swift-evolution@haravikk.me>:

I’m behind the idea in principle, but I’m not so sure we need a new
keyword for this:

for eachIndex in (1 ..< 10).by(2) { … }

The above would be adequate I thin, and just requires a new method on
ranges and similar types. This is being discussed, among other things, in
the c-style for loop discussion, as these were recently removed but without
a replacement for this type of use-case.

On 23 Mar 2016, at 21:40, David Knothe via swift-evolution < > swift-evolution@swift.org> wrote:

Hi,

I am new to Swift mailing list so I don’t know if this topic has already
been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a
specified step. Currently, if you would want to iterate over some odd
numbers, you had to write:
*for i in 1.stride(through: 7, by: 2) { … }*
What I think would be simpler and more convenient would be something like
the following:
*for i in 1 … 7 step 2 { … } . *Another option would be *for i in 1 … 7;
2 { … }*
The keyword ‚step‘ in this context clearly corresponds to the step of the
range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges
with a step ≠ 1. What do you think?
_______________________________________________
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


(David Knothe) #7

This is true indeed. Traversing over sets or similar would not be possible with a 'step' applied.
To fix this issue, an error could be generated when trying to apply 'step' on a for loop that does not iterate over a 'Strideable'.

I do not think an operator like ..+ is intuitive nor will it make code easier to read or write.

···

Am 24.03.2016 um 09:40 schrieb Xiaodi Wu <xiaodi.wu@gmail.com>:

If it's parentheses you want to avoid, you don't need a keyword to do that. For example, I can make a stride operator `..+` in four lines like so:

infix operator ..+ { associativity left precedence 134 }
func ..+ <Element: Strideable>(left: Range<Element>, right: Element.Stride) -> StrideTo<Element> {
    return left.startIndex.stride(to: left.endIndex, by: right)
}

// example of usage:
for i in 1..<10..+2 {
    print(i)
}

The point is, an extension on Range or a custom operator can be constrained so that Element conforms to Strideable. By contrast, for loops are used to traverse much more than just ranges. How do you envision your proposed keyword to interact with everything else? What if I had `var s: Set<Int>` and tried to write `for i in s by 2`--what do you think should happen? If you wish to limit `by` to ranges only, what is it about this particular function that makes it appropriate for a keyword of its own? You will need more to demonstrate how your proposal achieves what you claim, which is "improved ease and clearness."

On Thu, Mar 24, 2016 at 2:34 AM, David Knothe via swift-evolution <swift-evolution@swift.org> wrote:
I see your point that a simple extension on ranges and similar types would also do the thing.

But I do think that this is not as easy as many users would expect.
For example, I try to avoid parentheses in for loops as much as I can, but in your example, 4 additional brackets are required. A simple keyword („step" or „by“) would solve the problem seamlessly.

Also, a new template could be introduced that shows the existence of the new keyword:
<PastedGraphic-1.png>

I think adding such a new keyword would improve the ease and the clearness of the Swift language more than just adding some protocol extensions.

Am 24.03.2016 um 00:02 schrieb Haravikk <swift-evolution@haravikk.me>:

I’m behind the idea in principle, but I’m not so sure we need a new keyword for this:

  for eachIndex in (1 ..< 10).by(2) { … }

The above would be adequate I thin, and just requires a new method on ranges and similar types. This is being discussed, among other things, in the c-style for loop discussion, as these were recently removed but without a replacement for this type of use-case.

On 23 Mar 2016, at 21:40, David Knothe via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

I am new to Swift mailing list so I don’t know if this topic has already been discussed.

I like Swift's range operators ..< and …
What I am missing though is an easy operator to create a range with a specified step. Currently, if you would want to iterate over some odd numbers, you had to write:
for i in 1.stride(through: 7, by: 2) { … }
What I think would be simpler and more convenient would be something like the following:
for i in 1 … 7 step 2 { … } . Another option would be for i in 1 … 7; 2 { … }
The keyword ‚step‘ in this context clearly corresponds to the step of the range to create or to iterate over.

Essentially this is a syntactic sugar that makes it easy to create ranges with a step ≠ 1. What do you think?
_______________________________________________
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


(Brent Royal-Gordon) #8

That
would imply that floating types should not conform to Strideable,
which raises the question of whether Strideable should be folded into
the Integer protocol.

Personally, I get a lot of mileage out of conforming NSDate to Strideable. (Although obviously it ought to be using a float-friendly Strideable.)

···

--
Brent Royal-Gordon
Architechies


(Xiaodi Wu) #9

So, in other words, you'd be satisfied with the following addition to
the standard library?

extension Range where Element: Strideable {
    func by(step: Element.Stride) -> StrideTo<Element> {
        return startIndex.stride(to: endIndex, by: step)
    }
}

/*
example of usage:

for i in (1..<10).by(2) {
    print(i)
}
*/

My current thinking is that:

* `for x in 0.0..<3.0 {}` should probably be an error, because 1.0 is
  not the obviously-right stride to use for non-integral numbers. That
  would imply that floating types should not conform to Strideable,
  which raises the question of whether Strideable should be folded into
  the Integer protocol.

Well, maybe I'm missing something, but `for x in 0.0..<3.0 { }`
doesn't work as it is, and it doesn't seem to have anything to do with
Strideable. Rather, HalfOpenInterval<Double> doesn't conform to
SequenceType. I agree that `for x in 0.0..<3.0 { }` should continue
not working, but maybe let's keep floating point types conforming to
Strideable :slight_smile:

* `for x in (0.0..<20.0).striding(by: 1.3) {}` should work without
  accumulating error

+1.

* `for x in 0..<3 {}` should work (obviously; that's the status quo)

* `for x in (0..<20).striding(by: 2)` should work

I think this might also handle the concerns that
https://github.com/apple/swift-evolution/blob/master/proposals/0051-stride-semantics.md
was trying to address.

If I thought extreme concision was important for this application, I'd be
proposing something like

  for x in 0.0..<20.0//1.3 {}

but personally, I don't, which is why I propose `.striding(by: x)`
rather than simply `.by(x)`, the latter being more open to
misinterpretation.

Yeah, `.striding(by: x)` is pretty good.

···

On Thu, Mar 24, 2016 at 4:18 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Wed Mar 23 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

--
Dave

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


(David Sweeris) #10

I don’t think you'd even need a new operator. This works with Ints (haven’t tried anything else):
extension Strideable {
    func stride(by by: Self.Stride) -> (last: Self, by: Self.Stride) {
        return (self, by)
    }
}
func ..< <T: Strideable> (first: T, rhs: (last: T, by: T.Stride)) -> StrideTo<T> {
    return first.stride(to: rhs.last, by: rhs.by)
}
func ... <T: Strideable> (first: T, rhs: (last: T, by: T.Stride)) -> StrideThrough<T> {
    return first.stride(through: rhs.last, by: rhs.by)
}

Array(0..<10.stride(by: 2)) //[0, 2, 4, 6, 8]
Array(0...10.stride(by: 2)) //[0, 2, 4, 6, 8, 10]

···

On Mar 24, 2016, at 3:40 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

If it's parentheses you want to avoid, you don't need a keyword to do that. For example, I can make a stride operator `..+` in four lines like so:

infix operator ..+ { associativity left precedence 134 }
func ..+ <Element: Strideable>(left: Range<Element>, right: Element.Stride) -> StrideTo<Element> {
    return left.startIndex.stride(to: left.endIndex, by: right)
}

// example of usage:
for i in 1..<10..+2 {
    print(i)
}

(Hans Huck) #11

Dave Abrahams via swift-evolution <swift-evolution@...> writes:

If I thought extreme concision was important for this application, I'd be
proposing something like

  for x in 0.0..<20.0//1.3 {}

but personally, I don't,

And that is why exactly? The For-loop is at the very core of the language
and one of its most frequently used structures. Any unnecessary noise should
be avoided here.

which is why I propose `.striding(by: x)`
rather than simply `.by(x)`, the latter being more open to
misinterpretation.

Please elaborate. How could

for i in (1...10).by(3)

possibly be misinterpreted?

-- Hans


(Haravikk) #12

While I agree that ..+ isn’t the nicest operator choice, there may be other possibilities. It would be interesting if we could use regular letters as operators, as you could actually just declare your by or step keyword yourself in that way, but it could be specific to strideable ranges, though it may not be worth the chaos of everyone then declaring custom keywords everywhere.

Personally I don’t see the issue of requiring parenthesis to use (1 ..< 10).by(2), ultimately we’re still just iterating over a sequence, all we want is control over how a range’s sequence is generated, rather than it just using a stride of 1. A keyword is certainly prettier, but I think it’s better that developers know that there’s nothing new going on here, and that it’s still just a regular sequence like any other, rather than introducing a new structure that looks sort of like a new form of loop, but really isn’t.

···

On 24 Mar 2016, at 08:54, David Knothe <dknothe314@me.com> wrote:

I do not think an operator like ..+ is intuitive nor will it make code easier to read or write.


(Dave Abrahams) #13

That
would imply that floating types should not conform to Strideable,
which raises the question of whether Strideable should be folded into
the Integer protocol.

Personally, I get a lot of mileage out of conforming NSDate to
Strideable.

I just recalled that Unsafe[Mutable]Pointers are also Strideable. So
Strideable stays.

Question: by what unit should

        for d in d0...d2 {}

be iterating? Or should it be disallowed without a .striding(by: )?

If the latter, NSDate might fall into the same bucket as floating types.

···

on Thu Mar 24 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

(Although obviously it ought to be using a float-friendly
Strideable.)

--
Dave


(Dave Abrahams) #14

So, in other words, you'd be satisfied with the following addition to
the standard library?

extension Range where Element: Strideable {
    func by(step: Element.Stride) -> StrideTo<Element> {
        return startIndex.stride(to: endIndex, by: step)
    }
}

/*
example of usage:

for i in (1..<10).by(2) {
    print(i)
}
*/

My current thinking is that:

* `for x in 0.0..<3.0 {}` should probably be an error, because 1.0 is
  not the obviously-right stride to use for non-integral numbers. That
  would imply that floating types should not conform to Strideable,
  which raises the question of whether Strideable should be folded into
  the Integer protocol.

Well, maybe I'm missing something, but `for x in 0.0..<3.0 { }`
doesn't work as it is, and it doesn't seem to have anything to do with
Strideable. Rather, HalfOpenInterval<Double> doesn't conform to
SequenceType.

True, but the plan is that:

* Interval is going away
* Range will only require that its Bound be Comparable
* Ranges with Strideable bounds will conform to Collection

(see the swift-3-indexing-model branch on GitHub)

I agree that `for x in 0.0..<3.0 { }` should continue not working, but
maybe let's keep floating point types conforming to Strideable :slight_smile:

Those two things are not compatible with the plan we're going to
propose, as described above.

···

on Thu Mar 24 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

On Thu, Mar 24, 2016 at 4:18 PM, Dave Abrahams via swift-evolution > <swift-evolution@swift.org> wrote:

on Wed Mar 23 2016, Xiaodi Wu <swift-evolution@swift.org> wrote:

* `for x in (0.0..<20.0).striding(by: 1.3) {}` should work without
  accumulating error

+1.

* `for x in 0..<3 {}` should work (obviously; that's the status quo)

* `for x in (0..<20).striding(by: 2)` should work

I think this might also handle the concerns that
https://github.com/apple/swift-evolution/blob/master/proposals/0051-stride-semantics.md
was trying to address.

If I thought extreme concision was important for this application, I'd be
proposing something like

  for x in 0.0..<20.0//1.3 {}

but personally, I don't, which is why I propose `.striding(by: x)`
rather than simply `.by(x)`, the latter being more open to
misinterpretation.

Yeah, `.striding(by: x)` is pretty good.

--
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


(Dave Abrahams) #15

(p1..<p2).by(lineCount)

Doesn't exactly tell me what role lineCount is playing or what "by"
does. Maybe it means give me the range sorted by line count. In this
case a little more verbosity can be the difference between
understandable and unmistakable.

···

on Thu Apr 14 2016, Hans Huck <swift-evolution@swift.org> wrote:

Dave Abrahams via swift-evolution <swift-evolution@...> writes:

If I thought extreme concision was important for this application, I'd be
proposing something like

  for x in 0.0..<20.0//1.3 {}

but personally, I don't,

And that is why exactly? The For-loop is at the very core of the language
and one of its most frequently used structures. Any unnecessary noise should
be avoided here.

which is why I propose `.striding(by: x)`
rather than simply `.by(x)`, the latter being more open to
misinterpretation.

Please elaborate. How could

for i in (1...10).by(3)

possibly be misinterpreted?

--
Dave


(Erica Sadun) #16

(1..<11), (4..<14), (7..<17)...

-- E

···

On Apr 14, 2016, at 1:42 PM, Hans Huck via swift-evolution <swift-evolution@swift.org> wrote:
Please elaborate. How could

for i in (1...10).by(3)

possibly be misinterpreted?


(Hans Huck) #17

Dave Abrahams via swift-evolution <swift-evolution@...> writes:

> Dave Abrahams via swift-evolution <swift-evolution <at> ...> writes:
>
>>
>> If I thought extreme concision was important for this application, I'd be
>> proposing something like
>>
>> for x in 0.0..<20.0//1.3 {}
>>
>> but personally, I don't,
>>
> And that is why exactly? The For-loop is at the very core of the language
> and one of its most frequently used structures. Any unnecessary noise should
> be avoided here.
>
>> which is why I propose `.striding(by: x)`
>> rather than simply `.by(x)`, the latter being more open to
>> misinterpretation.
>>
> Please elaborate. How could
>
> for i in (1...10).by(3)
>
> possibly be misinterpreted?

  (p1..<p2).by(lineCount)

Doesn't exactly tell me what role lineCount is playing or what "by"
does. Maybe it means give me the range sorted by line count. In this
case a little more verbosity can be the difference between
understandable and unmistakable.

I find that unlikely, unless one is completely new to the language, but I
see your point -- for ranges in general.

It is impossible though to misinterprete it in the context of a For-loop, so
to keep the latter concise and the former unmistakable, what do you think of

for i in p1..<p2 by x

as syntactic sugar for and internally mapped to

for i in (p1..<p2).striding(by: x)

Best of both worlds?

-- Hans

···

on Thu Apr 14 2016, Hans Huck <swift-evolution <at> swift.org> wrote:


(Hans Huck) #18

Erica Sadun via swift-evolution <swift-evolution@...> writes:

> Please elaborate. How could
>
> for i in (1...10).by(3)
>
> possibly be misinterpreted?
>

(1..<11), (4..<14), (7..<17)...

Or (3..<30)? :slight_smile:

With that reasoning, "for in" would have to be changed to "for each" to
avoid possible misinterpretation; after all, "i" could be a range and "for i
in" could test if it's a subrange of (1...10).

Basically, there is no such thing as "unmistakable", not least because the
very same keywords and symbols are being used for different purposes in
different languages. There are only degrees of clarity.

Anyway, why not just make it .step() then, like in Ruby?

Instead of a "by" keyword, I'd be happy with syntactic sugar in the form of

for i in p1..<p2 step x

too, btw.

-- Hans

···

> On Apr 14, 2016, at 1:42 PM, Hans Huck via swift-evolution <swift-evolution <at> swift.org> wrote:


(David Knothe) #19

Well I would love to be able to create and use my own keywords / alphanumeric operators.
Depending on the type of code you are writing, these may be more or less helpful. The same is true for the 'step' keyword - maybe most people won't ever use it - but I think there should certainly be a possiblity, be it a concrete keyword built into the language or the possibility to create my own ones.

···

Am 24.03.2016 um 12:41 schrieb Haravikk <swift-evolution@haravikk.me>:

On 24 Mar 2016, at 08:54, David Knothe <dknothe314@me.com> wrote:

I do not think an operator like ..+ is intuitive nor will it make code easier to read or write.

While I agree that ..+ isn’t the nicest operator choice, there may be other possibilities. It would be interesting if we could use regular letters as operators, as you could actually just declare your by or step keyword yourself in that way, but it could be specific to strideable ranges, though it may not be worth the chaos of everyone then declaring custom keywords everywhere.

Personally I don’t see the issue of requiring parenthesis to use (1 ..< 10).by(2), ultimately we’re still just iterating over a sequence, all we want is control over how a range’s sequence is generated, rather than it just using a stride of 1. A keyword is certainly prettier, but I think it’s better that developers know that there’s nothing new going on here, and that it’s still just a regular sequence like any other, rather than introducing a new structure that looks sort of like a new form of loop, but really isn’t.


(Jordan Rose) #20

Strong vote to require a unit here, especially given that .minutes, .hours, .days, .months, and .years are all non-uniform intervals that are nonetheless useful to stride by!

Jordan

···

On Mar 25, 2016, at 9:19 , Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Thu Mar 24 2016, Brent Royal-Gordon <swift-evolution@swift.org> wrote:

That
would imply that floating types should not conform to Strideable,
which raises the question of whether Strideable should be folded into
the Integer protocol.

Personally, I get a lot of mileage out of conforming NSDate to
Strideable.

I just recalled that Unsafe[Mutable]Pointers are also Strideable. So
Strideable stays.

Question: by what unit should

       for d in d0...d2 {}

be iterating? Or should it be disallowed without a .striding(by: )?

If the latter, NSDate might fall into the same bucket as floating types.