`...` vs `..=` for inclusive ranges

Of course this exact example doesn’t require a ternary at all:

let res = if v < 0 { Err } 
else if v <= 10 { Ok("class 1") }
else if v <= 20 { Ok ("class 2") }
else { Ok("oversize") };

or with more clever formatting:

let res = 
     if v <  0  { Err } 
else if v <= 10 { Ok("class 1") }
else if v <= 20 { Ok("class 2") }
else            { Ok("oversize") };

Well... mine was just a simple example, but there could be 10 or 50 classes, are you suggesting to chain 10 or 50 if/else expressions?

From the Rust book, Match section:

Often, a simple if/else isn’t enough, because you have more than two possible options. Also, conditions can get quite complex. Rust has a keyword, match, that allows you to replace complicated if/else groupings with something more powerful.

is this true only for integers and strings?

Finally, following your reasoning, one could also say that the match expression is unnecessary because it can always be replaced with a series if/else expressions.

Instead of ternary operators, personally I would prefer to use ranges because:

  • They could be used both in if and match expressions (see examples above).
  • They are IMO easier to read and probably less complex to manage.
  • They would fit nicely with the current .. / ... notation.

Here is another example: to compute and plot function 1/x with x going from 0 (excluded) to 10 (included), it would be nice to write:

let x = (0.0>..10).step_by(0.001).collect::<Vec<_>>();
let y = x.iter().map(|x| 1.0 / x).collect::<Vec<_>>();

IMO notation ..., ..<, >.., >.< could nicely coexist with current .. / ... notation. The fact that .. and ..< would be equivalent may be acceptable (to avoid typing an additional character for the most common case), or otherwise .. could be deprecated in future.

1 Like

What does this mean? Start at 0, but reject it since it is not greater than 0, thus use first value 0.001? Or add some infinitesimal, say 10^-9? I've never seen an open range used to derive a sequence of values before, but I guess it's only the step_by function which is at fault here.

I have little against the proposed extension to range syntax (only that it's an extra feature). Possibly you should open an RFC, though @Gankra can advise you better on this.

(0.0..<10).step_by(0.001) means all values from 0 to 10 equally spaced with increments of 0.001, with 0 included and 10 excluded. Reversely, (0.0>..10).step_by(0.001) means all values from 0 to 10 equally spaced with increments of 0.001, with 0 excluded and 10 included. The first value would be 0.001.

That’s not a convention that was ever used when I studied my maths BSc, but I’ll take your word for it.

Let me clarify: I am not saying that it is a commonly used convention, of course in a math course you would for instance study function y = 1/x with x in interval (0, 10]. However, numerical methods such as finite difference rely on discretization, so (0.0>..10).step_by(0.001) would be a convenient way for discretization of the continuous interval (0, 10]. In my posts above I wanted to provide some use case examples of notation ..., ..<, >.., >.<, to explain why IMO they would be useful when dealing with floats. The primary use would be as patterns in match and if expressions. The secondary use would be for definition of ranges.

Let me clarify: there is nothing wrong with half-open ranges, but a function like step_by is going to have to make some arbitrary choices. (Even with closed ranges; for example what does [0...10].step_by(3) yield? Don’t answer that; I have a habit of writing rhetorical questions.)

But all that is besides the point. Whatever arguments you make, a feature is only ever going to be adopted if the right people are personally convinced that usefulness outweighs cost in real world usage (which doesn’t include contrived examples).

I don’t count as one of the “right people” BTW (nor do I want to), so stop trying to convince me.

Sorry to dredge this up if there has already been some resolution which i didn’t see, but…

How about ,, for inclusive ranges? The comma looks like a period with a tail, so ,, could be thought of as being like .. but with the tail element. Also (e.g.) 1,,10 looks like a shortened form of a mathematics-style 1, 2, …, 10.

Separately (and particularly when it comes to matching and floats), i would like like to see the syntax proposed by ecnahc515 ([1..10) etc) allowed. I realize it would be a big change, but the parens are balanced if you allow them to be matched with the brackets. I guess in this case a..b would be a shortcut form of [a..b), and a,,b would be a shortened form of [a..b].

RFC 1192 was accepted a week ago. The ... syntax will be used :smile:

They accepted it? Funny, I expect lots of newbies making an off by one dot errors.

1 Like

IMO, the difference between two and three dot is obvious with monospaced fonts. And every text editor I know use monospaced font.

Every other proposal I saw seemed unnatural.

4 Likes

Math

exclusive: [a..b), inclusive: [a..b]

Haskell

exclusive: <none>, inclusive: a..b

Elixir

exclusive: <none>, inclusive: a..b

Ruby

exclusive: a...b, inclusive: a..b

Swift

exclusive: a..<b, inclusive: a...b

Rust

exclusive: a..b, inclusive: a...b

Language designers be trolling. ¯\_(ツ)_/¯

3 Likes

Math exclusive: [a..b), inclusive: [a..b]

Where I am, in math the exclusive is written:

[a .. b[

Both is valid.

Here’s an idea for the syntax, straight from base math textbook:

0 <= .. <= 5	// inclusive, [0,1,2,3,4,5], same as ...
0 <= .. < 5	  // left inclusive, [0,1,2,3,4], same as ..
0 < .. <= 5  // right inclusive, [1,2,3,4,5]
0 < .. < 5  // exclusive, [0,1,2,3,4,5]

1 < .. < 1 // []
1 <= .. < 1 // []
1 <= .. <= 1 // [1]
2 <= .. <= 1 // []
a..b
a...b

becomes sugar for

a<= .. < b
a<= .. <= b

Good thing, it can be used the other way round for range constructors where the bounds are reversed (a >= b).

for i in 5 >= .. >= 0    // [5,4,3,2,1,0]
for i in 5 > .. >= 0    // [4,3,2,1,0]
for i in 5 >= .. > 0    // [5,4,3,2,1]
for i in 5 > .. > 0    // [4,3,2,1]
  • Reuses existing operators
  • Always read as “math”, easy to figure out for outsiders
  • Rust explicitness: both operators are mandatory, except when used in the “sugared” backwards compatible version
  • Spacing/separation TBD (but not ambiguous)
  • Looks like an extension of the existing syntax
  • No problems with open/close bracket rules
1 Like

That’s ambiguous as .. is already a valid range. Rust would parse that as 0 <= RangeFull <= 5.

Not necessarily. That would depend on the grammar.

Is 0 <= RangeFull <= 5 a valid construct?

You’re right, rust (probably) wouldn’t accept that as chained comparisons need parentheses.

However, personally, I’d find it quite confusing. When I see number - space - comparison operator, I assume I’m looking at a comparison.

1 Like

Fair enough. It depends on how used you are to stuff like say “0 ≤ x < 5”. I find it quite clear and straightforward. I do like the

[0, 5)

Notation quite a lot, but I’m sure if we adopted it it would wreak havoc in all existing editors, formatters and color highlighters.