the closed range operator

58 views
Skip to first unread message

Josh Brown

unread,
Jul 28, 2014, 8:46:40 AM7/28/14
to swift-l...@googlegroups.com
After the half-closed range operator change in Beta 3 (which I'm happy with), I started thinking about the closed range operator. Since they're both three characters now, it seems like it might make sense to use the equals sign at the end of the closed range operator instead of a dot. So instead of the following:

for index in 1...5 {
    println("\(index) times 5 is \(index * 5)")
}

It would be:



I talked to a friend about this who thought it was a good idea and said I should file a radar. I

Josh Brown

unread,
Jul 28, 2014, 8:50:55 AM7/28/14
to swift-l...@googlegroups.com
Oops - sorry, accidentally hit the wrong combination of keys and posted too early.

Would this make sense instead?

for index in 1..=5 {
    println("\(index) times 5 is \(index * 5)")
}

Before I go to radar, I thought I'd ask and hear others' opinions. With this approach, range operators would be more symmetrical/balanced (I'm not sure what the word is) - ..< and ..=What do you think?

Josh

Jens Alfke

unread,
Jul 28, 2014, 10:50:34 AM7/28/14
to Josh Brown, swift-l...@googlegroups.com

On Jul 28, 2014, at 5:50 AM, Josh Brown <jo...@roadfiresoftware.com> wrote:

Before I go to radar, I thought I'd ask and hear others' opinions. With this approach, range operators would be more symmetrical/balanced (I'm not sure what the word is) - ..< and ..=What do you think?

Ugh, no. At least one of them should remain simple and clean. The “=“ sign in there would make this easily confusable with assignment during quick skimming.

—Jens

Tom

unread,
Jul 29, 2014, 8:35:29 AM7/29/14
to swift-l...@googlegroups.com


On Monday, July 28, 2014 2:50:55 PM UTC+2, Josh Brown wrote:
Oops - sorry, accidentally hit the wrong combination of keys and posted too early.

Would this make sense instead?

for index in 1..=5 {
    println("\(index) times 5 is \(index * 5)")
}

Before I go to radar, I thought I'd ask and hear others' opinions. With this approach, range operators would be more symmetrical/balanced (I'm not sure what the word is) - ..< and ..=What do you think?
 
I think it's ok the way it is now. Try to see it like this:

The closed range (2...5) is symmetric, as it includes the first value and the last value: 2, 3, 4, 5. This is reflected by a perfectly symmetric operator "...".

The half-closed (half-open?) range (2..<5) is asymmetric, it includes the first value but not the last value: 2, 3, 4, !5. The asymmetry is consistently reflected by an asymmetrical operator "..<".

If you really would use the "=" sign in the closed range operator you had to write "=.=". Not very nice ;-) 

Josh Brown

unread,
Jul 29, 2014, 8:47:38 AM7/29/14
to swift-l...@googlegroups.com
That's a great point - I hadn't thought of it that way. Thanks for taking the time to explain your thoughts!

Andy Lee

unread,
Jul 30, 2014, 10:00:59 PM7/30/14
to Tom, swift-l...@googlegroups.com
On Jul 29, 2014, at 8:35 AM, Tom <th...@me.com> wrote:
> On Monday, July 28, 2014 2:50:55 PM UTC+2, Josh Brown wrote:
> Oops - sorry, accidentally hit the wrong combination of keys and posted too early.
>
> Would this make sense instead?
>
> for index in 1..=5 {
> println("\(index) times 5 is \(index * 5)")
> }
>
> Before I go to radar, I thought I'd ask and hear others' opinions. With this approach, range operators would be more symmetrical/balanced (I'm not sure what the word is) - ..< and ..=. What do you think?
>
> I think it's ok the way it is now.

I could live with it too, the way it is now, though it is not my preference.

There were at least two common complaints about the original operators: (1) they were too easy to confuse with each other, and (2) they would irk programmers who use Ruby, which uses the operators in the opposite way. Both complaints were not merely matters of taste; they were concerns about it being easy to make mistakes.

The current operators take care of (1). Josh's proposal (which I also suggested a while back and would prefer) would take care of (2).

> Try to see it like this:
>
> The closed range (2...5) is symmetric, as it includes the first value and the last value: 2, 3, 4, 5. This is reflected by a perfectly symmetric operator "...".
>
> The half-closed (half-open?) range (2..<5) is asymmetric, it includes the first value but not the last value: 2, 3, 4, !5. The asymmetry is consistently reflected by an asymmetrical operator "..<".
>
> If you really would use the "=" sign in the closed range operator you had to write "=.=". Not very nice ;-)

That's only if you assume that palindromicity of the operator is the only way to look at it. It happens to work for the current operators, but other possibilities also have reasonable mnemonics.

[The current way] x..<y and x...y
[Mnemonic] "..<" is asymmetric (and its meaning is clear), and "..." is symmetric (and easy to type). A drawback is that Ruby programmers might inadvertently type "..." to mean half-closed because that's still in their muscle memory from Ruby work they were doing ten minutes ago.

[Original Swift] x..y and x...y
[Mnemonic] As offered by Chris Lattner himself: "..." has one more character, indicating a range with one more element.

[Ruby style] x...y and x..y
[Mnemonic] The .. operator means closed range everywhere else, no mnemonic needed for that; in "...", the third dot "pushes" the last element out of the range.
[Alternate mnemonic] Three dots is an ellipsis, which means something is omitted.

[Josh's/my proposal] x..<y and x..=y
[Mnemonic] The operators have a parallel structure (partly why this version appeals to me): ".." means this is a range operator, "<" means the last element of the range is less than y, and "=" means it equals y.

[Yet another possibility] x..<y and x..y
[Mnemonic] ".." means closed range everywhere else. The "<" means the last element of the range is less than y. A drawback of this is that you could forget to type "<" when you should have.

--Andy

Jeremy Pereira

unread,
Aug 4, 2014, 5:14:59 AM8/4/14
to Andy Lee, swift-l...@googlegroups.com

On 31 Jul 2014, at 03:00, Andy Lee <ag...@earthlink.net> wrote:

>
> [The current way] x..<y and x...y
> [Mnemonic] "..<" is asymmetric (and its meaning is clear), and "..." is symmetric (and easy to type). A drawback is that Ruby programmers might inadvertently type "..." to mean half-closed because that's still in their muscle memory from Ruby work they were doing ten minutes ago.

Due respect to Ruby programmers, but why do we care if they have the operators the "wrong way around"[1]? Swift doesn't even take much notice of the muscle memory of Objective-C programmers. The number of times I've written

a = foo.doSomething: bar;

instead of

a = foo.doSomething(bar);

is at least several.


[1] Obviously, the right way around is somewhat subjective, but the idea that one more dot means one more value seems logical to me.

Tom

unread,
Aug 4, 2014, 8:20:06 AM8/4/14
to swift-l...@googlegroups.com
@Andy Lee, Thanks for the nice comparison.

That's only if you assume that palindromicity of the operator is the only way to look at it

Of course, nobody is forced to view it under the symmetry/asymmetry aspect.

[Mnemonic] As offered by Chris Lattner himself: "..." has one more character, indicating a range with one more element. 

Yes, this is a very good point too.

Not sure if I prefer the elegant original (pure-dot) notation or the more explicit new one. (But I prefer any of them over a "=" notation.)


To make it more visual:


The original notation:

Closed range "...":

|  starting value  | inbetween values |   final value    |
|         .        |         .        |         .        |

Half-open range "..":

|  starting value  | inbetween values |         –        |
|         .        |         .        |   [null marker]  |

The final value (element) is missing and this is represented by a missing final dot (missing index for the missing element). So, that notation is consistent A) regarding symmetry/asymmetry as well as B) regarding the representation of elements. But, unfortunately, if we look at an isolated ".." operator the asymmetry is lost, because it appears to be symmetric.


The new notation:

Closed range "...":

|  starting value  | inbetween values |   final value    |
|         .        |         .        |         .        |

Half-open range "..<":

|  starting value  | inbetween values |         –        |
|         .        |         .        |         <        |

Basically the same as with the old operators: The final value (element) is missing and this is represented by a missing final dot (missing index for the missing element). But now the null marker is replaced by a more explicit symbol "<". We could also say the "<" makes the null marker visible, or: the fact that the element is missing becomes apparent.

So this notation – just like the old one – is consistent A) regarding symmetry/asymmetry as well as B) regarding the representation of elements. But this time not only the missing element but also the asymmetry remains visible, even when we look at an isolated "..<" operator.


The "=" notation:

Closed range "..=":

|  starting value  | inbetween values |   final value    |
|         .        |         .        |         =        |

Half-open range "..<":

|  starting value  | inbetween values |         –        |
|         .        |         .        |         <        |

With this notation we double-lose consistency: in the symmetry/asymmetry department as well as in the elements department. Why should the final element be represented by another symbol as the other two if all of them are equally included?

The only advantage I see is that a confusion with ruby is less likely. But, honestly, I think from the moment on when you have learned the half-open "..<" you won't have a second of doubt about the meaning of the "...".

And at latest after having read this thread you won't ever forget it ;-)



Andy Lee

unread,
Aug 4, 2014, 9:27:41 AM8/4/14
to Jeremy Pereira, swift-l...@googlegroups.com
On Aug 4, 2014, at 5:14 AM, Jeremy Pereira <jeremy.j...@googlemail.com> wrote:
> On 31 Jul 2014, at 03:00, Andy Lee <ag...@earthlink.net> wrote:
>
>> [The current way] x..<y and x...y
>> [Mnemonic] "..<" is asymmetric (and its meaning is clear), and "..." is symmetric (and easy to type). A drawback is that Ruby programmers might inadvertently type "..." to mean half-closed because that's still in their muscle memory from Ruby work they were doing ten minutes ago.
>
> Due respect to Ruby programmers, but why do we care if they have the operators the "wrong way around"[1]? Swift doesn't even take much notice of the muscle memory of Objective-C programmers.

To frame it as us vs. them -- "Who cares how *they* feel? They sure don't care about us!" -- is to miss the point. The point is to minimize errors on our platform, for all comers. The tricky part is the tradeoffs in doing so.

--Andy

Jeremy Pereira

unread,
Aug 4, 2014, 9:34:02 AM8/4/14
to Andy Lee, swift-l...@googlegroups.com

On 4 Aug 2014, at 14:27, Andy Lee <ag...@earthlink.net> wrote:

>>
>> Due respect to Ruby programmers, but why do we care if they have the operators the "wrong way around"[1]? Swift doesn't even take much notice of the muscle memory of Objective-C programmers.
>
> To frame it as us vs. them -- "Who cares how *they* feel? They sure don't care about us!" -- is to miss the point. The point is to minimize errors on our platform, for all comers. The tricky part is the tradeoffs in doing so.
>
> --Andy
>

This is not about "us versus them" but about recognising that different languages do the same things in different ways. If there was some global standard syntax for ranges and it happened to coincide with the one used by Ruby, fine. However, by adopting Ruby's standard, maybe you are making it more difficult for some other group of programmers.

The objective should not be to ape some particular existing language (unless its ideas are good) but to come up with a clear easily understood syntax for _Swift_ programmers.

Andy Lee

unread,
Aug 4, 2014, 11:05:41 AM8/4/14
to Jeremy Pereira, swift-l...@googlegroups.com
On Aug 4, 2014, at 9:33 AM, Jeremy Pereira <jeremy.j...@googlemail.com> wrote:
> The objective should not be to ape some particular existing language (unless its ideas are good) but to come up with a clear easily understood syntax for _Swift_ programmers.

Nobody's talking about aping. In fact, the Ruby way is one of the few options I haven't seen an argument for. (I can imagine one; I just haven't seen it, certainly not on this thread.)

--Andy

Andy Lee

unread,
Aug 4, 2014, 11:12:10 AM8/4/14
to Tom, swift-l...@googlegroups.com
On Aug 4, 2014, at 8:20 AM, Tom <th...@me.com> wrote:

@Andy Lee, Thanks for the nice comparison.

That's only if you assume that palindromicity of the operator is the only way to look at it

Of course, nobody is forced to view it under the symmetry/asymmetry aspect.

Just to be clear: I think the symmetry aspect is a neat way of seeing the current operators, and as I said I can accept them as they are.  My point was less to criticize them (and definitely not to criticize your model) and more to point out there are ways to remember other possibilities too, including the **opposites** ".."/"..." and "..."/"..".  The existence of a mnemonic for one way of doing it does not automatically make that way better.


[Mnemonic] As offered by Chris Lattner himself: "..." has one more character, indicating a range with one more element. 

Yes, this is a very good point too.

Not sure if I prefer the elegant original (pure-dot) notation or the more explicit new one.

I would have to put the original notation way at the bottom of the possibilities we've discussed.  Set aside that it's practically hostile to Ruby developers.  Set aside the worries about 2 dots looking too similar to 3 dots (it's been a long time since I made a = vs. == mistake... though come to think of it, how could I possibly know that for sure!).  I think it was a mistake to have ".." mean half-closed when it has long meant closed everywhere else I'm aware of, not just in Ruby.  For that alone I'm happy about the change.

(But I prefer any of them over a "=" notation.)

At a certain point the discussion crosses into the realm of personal preferences, where different options appeal to how different people are wired.  One person's "elegant" is another person's "hideous" -- consider the spectrum of reactions that newcomers have had to Objective-C's messaging syntax.

I like the "=" because I see it as a qualifier for the ".." part of the operator that parallels the "<" in "..<".  Also it reminds me of what for-loops look like when I include the last value -- that's a strong visual cue for me.  You dislike the "=" because you see the operator as a whole -- all three characters combined -- as a sort of ideogram for the operation, so the "..." makes more sense to you.  At this point it's just Big-Endian vs. Little-Endian all over again.
Again, it depends on how you interpret the symbols.  My way is consistent in that the last character of each range operator is a comparison operator.  Your way is consistent in that the visual symmetry of each range operator corresponds to its mathematical symmetry.


The only advantage I see is that a confusion with ruby is less likely.

In practice, with the current operators (heck, even with the originals) Ruby-confusion might be a very minor edge case at worst, a non-issue at best.  I don't know enough to say.  I do know that if I were writing a book on Swift today I'd add a (small) side note that "..." has a different meaning in the two languages.  I would consider it worth mentioning.

But, honestly, I think from the moment on when you have learned the half-open "..<" you won't have a second of doubt about the meaning of the "...".

Sure, it will help a lot to know that those are the two operators and both have three characters.  If you stop and think, you can't go wrong, and hopefully it will become habitually ingrained.

And at latest after having read this thread you won't ever forget it ;-)

:) :)

--Andy

Reply all
Reply to author
Forward
0 new messages