Stream: ideas

Topic: chained comparison operators


view this post on Zulip Norbert Hajagos (Jan 22 2025 at 18:57):

I've always thought allowing a < b < c would be a net win for all languages that didn't coerce operandees of bool expressions into bools (think allowing 0 == false). In javascript this expression 3 > 2 > 1 is false, since it is true > 1 which is like saying 1 > 1. Not good. But in Roc, it would be a type mismatch (modulo the syntax error that right now notifies you to disambiguate with parens), so you wouldn't have to worry about this case. We could desugar this expression to a < b && b < c. I propose this sugar for these operators (<, <=. >, >=, == and != ). I think == and != are more debatable, but I would still include them, for completeness' sake.
At the same time, it is a small feature. It saves some &&s (or ands) to type, but the bigger discussion should be around Does this make the code more readable?. I think it doesn't make the code less understandable, not even with operator overloading (as long as we require them to return booleans). I haven't used a language that has it, like python or julia. I'm interested what you think about this feature in those languages and why you think it would or wouldn't have a place for it in Roc.

view this post on Zulip Sam Mohr (Jan 22 2025 at 19:13):

Do we plan on requiring that the desugared method of a.equals(b) -> c requires that b is of type a and c is of type Bool?

view this post on Zulip Sam Mohr (Jan 22 2025 at 19:13):

If so, this could be pretty helpful!

view this post on Zulip Sam Mohr (Jan 22 2025 at 19:16):

I expect more likely that we wouldn't raise an error at the equals method definition site that it has the wrong type, but more that the calling site would have a problem when equals returns a non-Bool and the == sign is used

view this post on Zulip Sam Mohr (Jan 22 2025 at 19:16):

And we could definitely use something like CalledVia internally to provide a better error message

view this post on Zulip Sam Mohr (Jan 22 2025 at 19:17):

On the subject of readability, this is probably a readability improvement for any list in the same direction, e.g. your a < b <= c

view this post on Zulip Norbert Hajagos (Jan 22 2025 at 19:20):

Yeah, I would only consider this feature if those rules would apply when using the comparison operators, whether enforced at the function definition, or at the use of the operator (tho I think the former would be a better experience "equas can only be defined if ..." than to say "MyNumber doesn't expose an equals function that has type MyNumber, MyNumber -> Bool" (while you actually have a function with a different signature.

view this post on Zulip Brendan Hansknecht (Jan 22 2025 at 19:31):

As long as we enforce good ordering sounds reasonable. It is a nice feature.

I have seen someone write the equivalent of x < 7 > y and I never want to allow that in roc.

view this post on Zulip Norbert Hajagos (Jan 22 2025 at 20:23):

Brendan Hansknecht said:

As long as we enforce good ordering sounds reasonable. It is a nice feature.

I have seen someone write the equivalent of x < 7 > y and I never want to allow that in roc.

Agreed.

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:54):

this seems reasonable to me in the case of less than/greater than combinations

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:54):

I don't think we should do it for others, including ==

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:55):

like 0 < x <= 10 is nice

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:55):

I don't think anyone looks at that and goes "what are these arcane runes? Rewrite this as 0 < x && x <= 10 so I can understand it"

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:56):

but x == y == z doesn't seem like it would come up as often, and also makes me think they're all booleans

view this post on Zulip Brendan Hansknecht (Jan 23 2025 at 03:56):

What about reverse ordering? 10 >= x > 0

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:57):

I could see an argument for parsing that and then reformatting it to be the other way, as long as they aren't expressions that would be lazily evaluated

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:57):

hm, actually that's interesting - should those short-circuit? :thinking:

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:58):

the fact that it isn't obvious just from looking at it makes me think maybe it's better not to support it, actually :sweat_smile:

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:58):

at least with and and or the semantics are clearly defined

view this post on Zulip Richard Feldman (Jan 23 2025 at 03:58):

even if it is more verbose

view this post on Zulip Sam Mohr (Jan 23 2025 at 04:06):

This is something we should maybe re-evaluate once we get some operator overloading + static dispatch usages in the wild

view this post on Zulip Richard Feldman (Jan 23 2025 at 04:07):

it definitely feels very low-impact either way haha

view this post on Zulip Richard Feldman (Jan 23 2025 at 04:07):

like having it or not having it doesn't seem impactful

view this post on Zulip Sam Mohr (Jan 23 2025 at 04:08):

Which is why I'd lean away from it

view this post on Zulip Richard Feldman (Jan 23 2025 at 04:09):

"don't add unimportant features" is definitely the right default, yeah :big_smile:

view this post on Zulip Sam Mohr (Jan 23 2025 at 04:09):

We should add stuff that we think is a positive, not likely to be a positive. A small language takes constant pruning efforts

view this post on Zulip Norbert Hajagos (Jan 23 2025 at 09:14):

For me, looking at it, short circuiting is "obviously happening", but yeah, you can't see the explicit &&s, so it isn't a no-brainer.
All arguments are good. To have a more definitive answer, before I mark as resolved, I'll ask: Which way are you leaning towards:

  1. "Revisit it later, after more important work is done"
  2. "Not worth it for an extra feature"?

view this post on Zulip Sam Mohr (Jan 23 2025 at 09:26):

I lean more towards one. Definitely not a bad feature, just not sure if enough people would end up using this.

view this post on Zulip Sky Rose (Jan 24 2025 at 02:06):

I lean towards 1. It's relatively low cost (totally optional to do, easy to understand if you see it even if you didn't know it was possible) and I think the benefits are small but certain.

In a past life teaching python to college students I saw beginners make this mistake all the time, cuz x < y < z is used in math classes, and it'd be nice if that speedbump didn't exist.

And it's another thing that would make Roc faster and easier to write for quick scripts.

But I do see the risk in adding every feature that seems like a good idea. In this case it makes it less clear what counts as an expression.

view this post on Zulip Richard Feldman (Jan 24 2025 at 02:08):

we could have the parser accept it and then special-case an error for it that tells you what to write instead

view this post on Zulip Richard Feldman (Jan 24 2025 at 02:08):

and have the formatter auto-replace it with and

view this post on Zulip Sam Mohr (Jan 24 2025 at 02:09):

Seems like it wouldn't be that hard to extend that out of our PrecedenceProblem reporting

view this post on Zulip Norbert Hajagos (Jan 24 2025 at 08:50):

Can the formatter fix your code this way? Thought it wasn't allowed to change the resulting AST - a restriction we ourselves put on it though. My first thought is that if we consider that, I would rather see it allowed in the compiler, since it is even less gain for ... quick estimation about something I have 0 experience in ... a relatively similar effort.

I had the same intuition as @Sky Rose . It just makes sense if you've seen it in math.


Last updated: Jun 16 2026 at 16:19 UTC