Stream: beginners

Topic: Wrong boolean operator result


view this post on Zulip Kilian Vounckx (May 14 2023 at 21:00):

Not sure if this is the right stream for this, but I wanted to check here before raising an issue.
I was playing around with roc and I think I found a bug. A minimal reproduction can be done in the repl:

Bool.false && Bool.false || Bool.true && Bool.true

This should give Bool.true as a result (simplifies to Bool.false || Bool.true), but it gives Bool.false.
Is this a known issue? I am using a compiler built from source yesterday

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:01):

Adding parenthesis around the two '&&' comparisons makes it work, which makes me think it is an issue with the order of operations

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:01):

Does || run before &&....is that correct? Don't recall normal ordering rules.

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:02):

Simplify to Bool.false && Bool.true && Bool.true

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:05):

In every programming language I know of && runs before ||

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:05):

In electronics and mathematics the and operator also has precedence

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:06):

Not python (assuming i just typed this in correctly) nvm...typed it wrong

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:07):

False and False or True and True

This in a python repl gives True

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:12):

It is a super easy fix, looks like we have a precedence table and they are equal precedence currently.

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:13):

https://github.com/roc-lang/roc/blob/cfcd2a52892cc5ef0cf3ba9a33007820aa57d596/crates/compiler/module/src/called_via.rs#L21-L22

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:14):

Just incrementing all precedence by 1 except for OR is a fix.

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:14):

Then and has a precendence 1 higher. Not sure if we picked equal precedence for a specific reason.

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:15):

I always use parens in cases like these

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:20):

Because they are equal precedence, this is current behaviour:

Bool.false && Bool.false || Bool.true && Bool.true

# is running as:

Bool.false && (Bool.false || (Bool.true && Bool.true))

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:21):

Oh I see
I think it is best to have either && be higher precedence, or have the compiler enforce you to put parens

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:22):

Probably. No idea why it is this way, just digging into the compiler and noting how it currently is.

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:23):

Should I raise an issue for it?

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:23):

I could probably fix it myself, but it would be tomorrow (in my timezone it is almost midnight)

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:24):

That is probably reasonable. Though should wait for a comment from someone else before fixing. It may be working as intended. I don't know the background here. But yeah, fix is super simple, I already have one.

view this post on Zulip Martin Stewart (May 14 2023 at 21:25):

I'd like to second the idea of the compiler forcing you to place parens when && and || are used. I can never keep straight which takes precedence (unlike +, -, *, /, ^). That said, fixing the precedence seems fine otherwise.

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:28):

issue raised

view this post on Zulip Kilian Vounckx (May 14 2023 at 21:30):

Martin Stewart said:

I'd like to second the idea of the compiler forcing you to place parens when && and || are used. I can never keep straight which takes precedence (unlike +, -, *, /, ^). That said, fixing the precedence seems fine otherwise.

I'm from an electrical engineering background where these operators are used a lot. In my case I never confuse them, which is why I found the output in roc odd. So my preference is having the correct precedence.
Also fine with the enforced parenthesis though

view this post on Zulip Martin Stewart (May 14 2023 at 21:31):

I guess it depends how many other people find it difficult to remember boolean operator precedence.

view this post on Zulip Brendan Hansknecht (May 14 2023 at 21:37):

@Richard Feldman or @Folkert de Vries any history on this ordering? Is it a bug or is it intentional for some specific reason?

view this post on Zulip Georges Boris (May 14 2023 at 21:50):

I'm +1 for compiler warning here - seems similar to confusing infix functions in a pipeline like |> ((/) 2 (elm)

I can understand it might be obvious if the person knows the caveat but imo Roc is trying to push for making things safe even for beginners so a compiler warning for error-prone assignments seems the right choice

view this post on Zulip Richard Feldman (May 14 2023 at 22:05):

I'm pretty sure I just started with whatever Elm did on that

view this post on Zulip Richard Feldman (May 14 2023 at 22:06):

I like the idea of forcing parens there :thumbs_up:

view this post on Zulip Ajai Nelson (May 14 2023 at 22:10):

It looks like Elm returns true:

> False && False || True && True
True : Bool

view this post on Zulip Brendan Hansknecht (May 14 2023 at 22:16):

Cool. So then two issues. 1 fix the precedence to match elm and most programming languages again

view this post on Zulip Brendan Hansknecht (May 14 2023 at 22:17):

2 force parens

view this post on Zulip Richard Feldman (May 14 2023 at 23:12):

I think if we force parens the precedence becomes moot, no?

view this post on Zulip Brendan Hansknecht (May 14 2023 at 23:16):

Oh, i was thinking warning if no parens, so precedence still matters. For example in repl or dev

view this post on Zulip Brendan Hansknecht (May 14 2023 at 23:16):

If we make parens 100% required than it is moot

view this post on Zulip Richard Feldman (May 14 2023 at 23:27):

ah fair

view this post on Zulip Richard Feldman (May 14 2023 at 23:27):

good idea about making it a warning :thumbs_up:

view this post on Zulip Richard Feldman (May 14 2023 at 23:27):

in that case, yeah might as well change the precedence too

view this post on Zulip Agus Zubiaga (May 14 2023 at 23:43):

Do warnings make sense for Roc when roc run runs your program even with compiler errors?

view this post on Zulip Richard Feldman (May 14 2023 at 23:51):

yeah, the distinction is:

view this post on Zulip Agus Zubiaga (May 14 2023 at 23:52):

Ah, the nonzero exit code is key. Without that I'd be worried it would result in the usual pile of ignored warnings.

view this post on Zulip Richard Feldman (May 14 2023 at 23:53):

yeah my experience on warnings is that if it's hard to ignore them from day 1, they'll never pile up

view this post on Zulip Richard Feldman (May 14 2023 at 23:53):

but of course they still shouldn't block running your program if you don't want to deal with them right away (and neither should errors!)

view this post on Zulip Agus Zubiaga (May 14 2023 at 23:54):

Yeah, that's a good balance :)

view this post on Zulip Anton (May 15 2023 at 08:33):

This kind of warning seems to be most suited for the formatter.

view this post on Zulip Brendan Hansknecht (May 15 2023 at 14:16):

So no warning when doing roc run/dev/build? Only a warning on roc format?

view this post on Zulip Brendan Hansknecht (May 15 2023 at 14:17):

I would be concerned that roc format won't be in the hot loop enough to get cared about, even if it gives a warning. So I guess this depends on if we think that in general this should be fixed or if we don't care too much. Personally, I always add the parens in these kinds of cases, so I am totaly happy with the compiler warning and this being enforced in general. I think using them directly is simply more error prone and harder to read.

view this post on Zulip Anton (May 15 2023 at 14:21):

So no warning when doing roc run/dev/build? Only a warning on roc format?

Yes, that's what I was thinking

I think using them directly is simply more error prone and harder to read.

I agree, but this seems the case for a lot of things that are currently fixed by the formatter :p

view this post on Zulip Brendan Hansknecht (May 15 2023 at 14:24):

Would the formatter give a warning, or just fix it by adding in the parens as roc sees it?

view this post on Zulip Brendan Hansknecht (May 15 2023 at 14:24):

Cause that is what actually would get parsed?

view this post on Zulip Agus Zubiaga (May 15 2023 at 14:37):

Automatically adding parens sounds dangerous because it might happen somewhere you're not currently looking at and you might not notice the warning which won't appear in subsequent runs.

view this post on Zulip Anton (May 15 2023 at 14:39):

I first thought that the formatter should add parens as roc sees the order but then it might be easy to miss that the order is not how you want it. So maybe a compiler warning is more appropriate

view this post on Zulip Agus Zubiaga (May 15 2023 at 14:40):

Yeah, that's what I think as well. Also, I'm not sureroc format warnings should be a thing as users will likely run it automatically on save and they'll probably miss them. At least that's what (almost) everybody does in Elm.

view this post on Zulip Kilian Vounckx (May 15 2023 at 16:34):

If there are going to be compiler warnings for these operators, should there be a discussion for others as well (comparison operators vs equality operators,...)?

view this post on Zulip Richard Feldman (May 15 2023 at 17:08):

yeah totally, and personally I've thought for years that we should do warnings like this for arithmetic operators

view this post on Zulip Richard Feldman (May 15 2023 at 17:08):

e.g. 1 + 2 * 3 - 4 should be explicitly rewritten to 1 + (2 * 3) - 4


Last updated: Jul 06 2025 at 12:14 UTC