Crystal: Consider removing exclusive range literal syntax (triple dot) for ranges

Created on 30 Mar 2017  路  22Comments  路  Source: crystal-lang/crystal

Just support "..", it covers all use cases already and leads to less confusion.

draft compiler

Most helpful comment

Should all four exclusiveness ranges be supported, then?

foo...bar
foo>..bar
foo..<bar
foo>.<bar

The last one would be quite amazing.

All 22 comments

I actually agree. The common usecases for the triple dot are things like index iteration, for which we often have dedicated support on a collection and if not I prefer Int#to anyway. I maybe once or twice used the triple dot in Ruby but never in Crystal.

@vegai How do you make a method that, given a string, returns a new one without the last char?

self[0..-2]

Well, I knew I shouldn't have said "covers all use cases" so lightly. Nevertheless, initially it kinda seems like ... serves only to confuse. I always thought so when coding Ruby.

Index queries return a value that needs to be used with -1 if ... goes away.

As for Crystal itself, there are about a hundred lines of code that need to be changed in compiler and libraries if syntax is changed like this. Mostly foo...bar => foo..bar-1. I'll have a branch about this later today I believe.

foo .. (bar - 1) is an ugly replacement.

I understand that ... might be natural only for rubyists. It's true does not read that fluent. You need to "count the dots" there to know if it's inclusive or exclusive.

But I think there is value in exclusive and inclusive literals.

If the complain is about syntax there could be other alternatives. Sadly the math notation can't be used because [ and ( have other semantic and having non pairing braces in the code will be painful for editors.

So instead of the current foo...bar, we could imagine other alternatives.

  • foo.,bar (and could allow ,. and ,,)
  • foo..<bar (it is used in Swift and Fantom)

Well, I'm somewhat of a rubyist, and ... doesn't seem natural to me :) The intuition is all wrong, IMHO.

1..2
1...2

The latter range should be larger, shouldn't it? Because 1 and 2 are farther apart.

As for foo..bar-1 (parens are not needed here, I think?) being ugly, I do agree. But I claim that it's not as problematic as foo...bar

@vegai The extra dot pushes the right side a bit further, so it leaves it out of the range

As a general comment, though, many here at Manas (including myself) always found .. vs ... a bit confusing, so this is definitely a valid concern and something that we'll eventually sort out.

FWIW, I'd personally dump .., since ... is akin to Python's range.

I guess the source of my intuition comes from a year of being near Rust. https://is.gd/LZBipj -- their range literal syntax is as I described, with ... being the inclusive range.

foo..<bar imho looks very nice - it's evident what it means even to somebody who aren't sure if .. is inclusive.

Should all four exclusiveness ranges be supported, then?

foo...bar
foo>..bar
foo..<bar
foo>.<bar

The last one would be quite amazing.

If we're going this way, I vote to remove both notations a..b and a...a in favor to explicit Range.new(a, b) and Range.new(a, b, exclusive: true) or nicer constructs like a.upto(b), instead of adding some new notation (IMHO weirder and more confusing).

I wouldn't add new notations. As for the current ones, I'm ok with removing ..., but I'm also ok leaving as is. Removing it isn't terrible since .. lets you do all you need, even if at times it becomes a bit verbose. I definitely wouldn't remove the ... It'd make code like this much less compact and more difficult to understand:

https://github.com/mverzilli/crystalla/blob/master/spec/matrix_spec.cr#L595

@mverzilli Well... float ranges is one place where .. doesn't give you everything.

rand(1.0..2.0)
rand(1.0...2.0) # cannot really do this via ..
rand(1.0..(2.0-epsilon)) # auch
rand(Range.new(1.0, 2.0, true))) # also a bit auch

It seems to me like the use cases for exclusive range are larger than of inclusive (personally, I've almost never had to use the latter), especially in the case of indexing.

@ysbaddaden I would think the use case for ranges is too common (mostly in indexing) to outright remove the syntax from the language. Imagine a[b..c] turning into a[Range.new(b, c)].

I like having both inclusive and exclusive ranges. But it's also true that even after many years of writing ruby, I frequently go into irb to make sure whether what I want is .. or .... I like the Swift syntax of ..<.

Side note: I think this should be labeled as topic:syntax instead of topic:compiler

There is an interesting disc on stack exchange: https://softwareengineering.stackexchange.com/questions/64975/designing-the-perfect-range-literal
Although, it mostly favours brackets similar to the mathematical notation, which is not feasible for Crystal as per @bcardiff.
I find 0..!5 a notable variant of 0..<5, though. It feels nicer...

I suppose this ain't going nowhere? Closing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

RX14 picture RX14  路  3Comments

grosser picture grosser  路  3Comments

asterite picture asterite  路  3Comments

lgphp picture lgphp  路  3Comments

oprypin picture oprypin  路  3Comments