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
Adding parenthesis around the two '&&' comparisons makes it work, which makes me think it is an issue with the order of operations
Does ||
run before &&
....is that correct? Don't recall normal ordering rules.
Simplify to Bool.false && Bool.true && Bool.true
In every programming language I know of &&
runs before ||
In electronics and mathematics the and operator also has precedence
Not python (assuming i just typed this in correctly) nvm...typed it wrong
False and False or True and True
This in a python repl gives True
It is a super easy fix, looks like we have a precedence table and they are equal precedence currently.
Just incrementing all precedence by 1 except for OR is a fix.
Then and has a precendence 1 higher. Not sure if we picked equal precedence for a specific reason.
I always use parens in cases like these
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))
Oh I see
I think it is best to have either &&
be higher precedence, or have the compiler enforce you to put parens
Probably. No idea why it is this way, just digging into the compiler and noting how it currently is.
Should I raise an issue for it?
I could probably fix it myself, but it would be tomorrow (in my timezone it is almost midnight)
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.
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.
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
I guess it depends how many other people find it difficult to remember boolean operator precedence.
@Richard Feldman or @Folkert de Vries any history on this ordering? Is it a bug or is it intentional for some specific reason?
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
I'm pretty sure I just started with whatever Elm did on that
I like the idea of forcing parens there :thumbs_up:
It looks like Elm returns true:
> False && False || True && True
True : Bool
Cool. So then two issues. 1 fix the precedence to match elm and most programming languages again
2 force parens
I think if we force parens the precedence becomes moot, no?
Oh, i was thinking warning if no parens, so precedence still matters. For example in repl or dev
If we make parens 100% required than it is moot
ah fair
good idea about making it a warning :thumbs_up:
in that case, yeah might as well change the precedence too
Do warnings make sense for Roc when roc run
runs your program even with compiler errors?
yeah, the distinction is:
crash
, so your program may crash if you run it anyway"crash
, but you should really fix it; it will cause the process to exit with a nonzero exit code, and therefore fail CI" (and alaso if you're a package, this will block being able to publish on the official registry)roc dev
will run as soon as there are no errors, even if there are still warningsAh, the nonzero exit code is key. Without that I'd be worried it would result in the usual pile of ignored warnings.
yeah my experience on warnings is that if it's hard to ignore them from day 1, they'll never pile up
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!)
Yeah, that's a good balance :)
This kind of warning seems to be most suited for the formatter.
So no warning when doing roc run/dev/build
? Only a warning on roc format
?
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.
So no warning when doing
roc run/dev/build
? Only a warning onroc 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
Would the formatter give a warning, or just fix it by adding in the parens as roc sees it?
Cause that is what actually would get parsed?
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.
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
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.
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,...)?
yeah totally, and personally I've thought for years that we should do warnings like this for arithmetic operators
e.g. 1 + 2 * 3 - 4
should be explicitly rewritten to 1 + (2 * 3) - 4
Last updated: Jul 06 2025 at 12:14 UTC