The problem I'm trying to solve is else ifchains...
**If we adjusted the meaning of else to mean the last branch
in a possibly multi-branched decision structure.** (Very similar to the meaning of _->)...
Then we could have the following:
if x < 10 then "small" else "big"
if x < 10 then
"small"
else
"big"
if x < 10 then
"less than ten"
x < 100 then
"less than 100"
x < 1000 then
"less than 1000"
else
"big"
when val is
LessThenTen ->
"small"
else
"big"
This has the advantage of permitting a single line if..else (which @Richard Feldman has expressed a desire for) without a change in syntax for that use case.
This does introduce more indentation than the existing muliline else..if chain. However improves readability and has the same indentation as when..is currently.
Writing else if would still be possible but would give a compiler warning.
For previous discussion of rejected proposals see :
https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/Prevent.20.60else.20if.60
https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/elif.20syntax
https://roc.zulipchat.com/#narrow/stream/304641-ideas/topic/cond-like.20if.20syntax
For the possible alternative of expanding when..is to permit matching on expressions of different types:
Brendan Hansknecht said:
I think that
whenwith full expression support instead of just constants with binding variables could potentially enable super powers, but I am not sure if it would be reasonable. Likely it would enable a large set of confusing code, but I am not really sure cause I haven't messed with it enough. A few examples off the top of my head:Be used instead of
ifas mentioned above:when Bool.true is num < 10 -> "less than 10" num < 100 -> "less than 100" num < 1000 -> "less than 1000" _ -> "it's a big number"try multiple things until the first
Okresult and then do something.
EachOkcan be handled different in each branch.when Ok _ is List.get someList 3 -> ... Num.addChecked x y -> ... somePossiblyFailingFunction a b -> ... _ -> crash "everything failed"Theoretically if the types line up, you could write
when Ok val isfor the first line of the above example. That would enable still binding the wrapped value and using it in sub branches. I guess this is another way to write a chaining of results with special handling on failure, but it is still intriguing.I assume something of this nature would actually be very powerful and interesting, but my gut feeling is that it would be too powerful and lead to more confusing code rather than be positive overall.
The example looks good but now we have double indentation again. The double space after the if is also unusual.
Yes! but that extra space after if could be:
when..is. The double indentation complaint really has to be levied against when ..is as well.
In the worst case we wouldaccept typing two spaces because thats still way better than typing else if a bunch of times and having all the else if's there to obscure the conditions as well as pushing the conditions out of alignment.
Aside from solving the visual issues with else..ifthis syntax has the positive side effects of:
reduced typing over a multi-branched if..else
else as the last condition. whereas in a multi-branch if..else that's not true.it leads naturally to the pleasing (?) syntax of else being overloaded to have a similar meaning which can displace _ -> for when..is (as illustrated in the last example above. Obviously this is non-essential if not desired. This use of else in the when..is structure could widely be seen as actually normalizing the when..is to more conventional syntax. Which would actually (in that regard, undo some of roc's "strangeness budget" spending.
It seems like this structure makes a better compromise:
if
x < 10 then
"less than ten"
x < 100 then
"less than 100"
x < 1000 then
"less than 1000"
else
"big"
It requires no double space or a unique-in-the-language double indent for the next line
@Anton
That's a 5th resolution to the double space after if issue.
I'm fine with that. I'm afraid other people won't be. I'm thinking the proposed way looks more conventional and requires one less vertical new line.
I found that the issue with "double space after if" doesn't seem bad if I think of it as a tab.
Would there be heavy opposition to going to 3 space indentation (which would eliminate this issue of "two spaces after if" and, as I said also mitigates the "issue of indentation" for this idea as well as for when is )? Nim uses 2 space indentation, so three must be doable.
Three spaces could look good visually but it will likely be very surprising to users. It is generally a good idea to prevent surprising the user. This is not a definitive no for me however.
I see. Is Nim's 2 space indentation surprising? (honest question)
I guess I'm just not familiar with indentation conventions. Obviously, based on what you're saying 4 spaces must be common.
@Anton Does the "two spaces after if issue" change for you if you think of it as a tab? If I think of it as a tab I don't feel it's bad.
I see. Is Nim's 2 space indentation surprising? (honest question)
A little, but it definitely seems acceptable, going with an odd number is a degree further
thanks
I guess I'm just not familiar with indentation conventions. Obviously, based on what you're saying 4 spaces must be common.
I think 4 spaces is the most common or a tab that looks like 4 spaces in the editor
Anton Does the "two spaces after
ifissue" change for you if you think of it as a tab? If I think of it as a tab I don't feel it's bad.
It's again very surprising to new users.
Yes it's still a potential stumbling block, but the compiler doesn't have to stop everything if someone only enters one space instead of hitting tab.
Actually I would say the tab after if is not even necessarily a stumbling block, because I can't see how it has to ever cause an actual inconvenience. Even when learning roc, things could just work if someone just puts 1 space after if and the condition. It just eats a bit into the wierdness budget if people think of it as 2 spaces and not a tab. (But this proposal also reduces the wierdness budget as well in other ways).
The double indent before "less than ten" will not play nice with any existent tooling
if x < 10 then
"less than ten"
x < 100 then
"less than 100"
x < 1000 then
"less than 1000"
else
"big"
x < 100 then lining up with x < 10 and not the beginning of the line is unique in the language as well.
I would prefer going with 3 spaces.
It seems excessive to do it just so that our if lines up well but it could be nice to prevent excessive indentation in the language in general.
Anton said:
The double indent before "less than ten" will not play nice with any existent tooling
if x < 10 then "less than ten" x < 100 then "less than 100" x < 1000 then "less than 1000" else "big"
x < 100 thenlining up withx < 10and not the beginning of the line is unique in the language as well.
For my edification, why is that? (That the existing tooling will not play nice if there is indentation on the same line as if?)
Double indent after the user presses enter after the then keyword may require changes to the code of existing editor language plugin systems because no other language does it like this. Exceptional situations require exceptional handling.
I also expect that editors that newly support roc will get this indenting wrong in their initial implementation.
Ok, I see thanks.
So I guess that's unfortunate but workable if the editor doesn't get it right (basically by hitting an extra tab) and solvable with potentially some extra work on an editor plugin.
wouldn't this work?
if x < 10 then
"..."
if x < 100 then
"..."
else
"..."
we're just impling an else in any if followed by other if in the same level of indentation.
if someone wrote else if the formatter could fix it (and it would still be a valid syntax, just no the standard one)
no extra indentation.
btw I'm basically ok with status-quo. just trying to push the ideas a bit.
This could be it!
Of all the proposals, this is the one I like the most
I proposed this syntax in one of the other threads. I like it personally. Fixes lining everything up. Also, since Roc conditionals are always terminating, you can't have issue with hanging branches. As in, this is impossible:
if x < 10 then
"..."
if x < 100 then
"..."
# An else branches is required here in Roc
# I can not do something else outside of the if/else here
I like that a beginner can just do else if and that would work fine
And simple if/else cases look just like they do now without the extra line and indent
I guess my only concern with the syntax is that someone might assume there is a bug and try to correct tabbing in certain cases.
Did you mean to do:
if x < 10 then
"..."
if x < 100 then
"..."
or did you want:
if x < 10 then
"..."
if x < 100 then
"..."
Having the else if makes this clear.
They would end up with a missing else if they did that, wouldn't they?
if x < 10 then
"..."
if x < 100 then
"..."
# Missing else
else
"..."
Or
if x < 10 then
"..."
if x < 100 then
"..."
else
"..."
# Missing else
Less obvious than else if, but they would still get a syntax error
oh yeah, there would be two else branches in correct code, so you couldn't just untab it. You would need to delete an else branch.
Ok. concern not a problem...yeah, I approve this syntax.
Also that ... in the first if would have to be a "terminal" expression which I think could never be followed by an if in the next line
It really the same as a language like c where you may see:
if (x < 10) {
return "...";
}
if (x < 100) {
return "...";
}
return "...";
Just in our case, the return is implicit and the final return is wrapped in an else. So should be quite readable to others.
I like it a lot better than else..if but what really matters is not why you or I think, or what R.F. thinks, but I think what matters is what R.F. thinks newcomers will think when they see it. :grinning:
Our thoughts definitely matter. Richard will read them and take that into consideration. He may be the final decision on most of these, but community input has a huge effect on the outcomes.
(for the record... I wasn't questioning that)
so just to check my understanding: the proposal is that if followed by another if is basically syntax sugar for the second one being else if except you can omit the else?
whose proposal?
the current one
I'm saying that else should mean the end of the decision structure
that way a single line if works as usual, and multiline if then can be had as well
the suggetion that a bunch of people are just proposing is compatible with that, they are just saying that each line should be started with if (where in my original version I would just indent).
...their suggestion means that this would not be an indented structure. (and solves a potential quirk in my proposed syntax, which is that people would hit tab after typing if and before the first condition.
ah I see
else meaning the end has a bunch of benifits which I've outlined early in the thread.
Yeah, would mean that if followed by if is just syntax sugar for if followed by else if
I guess also would potentially propose that roc format automatically removes the unneeded else in else if.
To keep roc code looking consistent and help push towards one way to write that.
Brendan Hansknecht said:
Yeah, would mean that
iffollowed byifis just syntax sugar foriffollowed byelse if
Yes but not exactly if else always means the end of the decision structure.
...it's a different meaning of else than we currently have.
Ah, I see, I guess I had considered that two different proposals, can you give an example of how they merge?
Matthias Toepp said:
...it's a different meaning of
elsethan we currently have.
but of course the body of the else is an expression, and if is a valid expression, so as noted previously - else if would still be supported by default :big_smile:
unless you specifically made else with an if inside be a syntax error
one difference would be that with implying that there could be multiple conditons inside a single if..else (as I'm implying) then that woud mean that writing if again after else would require further indentation as I proposed it.
...but an existing if..else (proposed) structure could have branches added inside it.
(without the added indentation that one would get by writing else after if (in the proposal)
and yes we could then give a warning if someone writes if after else.
If you require the indentation, wouldn't that remove single line if?
If not, I think you would still potentially see else if.
I wrote out the examples at the top of the thread
I'm trying to get away from else..if, so just now I was saying that if people do it wrong and try to use if immediately after else then it would look strange and require extra indentaion and give a warning.
...where as adding extra conditions before else refactors nicely.
If you support single line if ... else, someone can write an if in the else branch, so else if will still exist without any indent. Just only if you do it on a single line. That is just the strange syntax edge case I am trying to point out.
if always exists but gives a warning.
..if it's used after else
ok
...because this syntax doesn't require doing else if.
so else if would be possible but be a strong code smell. And pointed out by the compiler.
Matthias Toepp said:
so
else ifwould be possible but be a strong code smell.
I understand that this is what you're going for, but I have a really negative gut reaction to this idea. Like else if is such an extremely normal thing in programming! Why are we trying so hard to get rid of it? :sweat_smile:
to me, "strong code smell" is reserved for things that cause bugs
it would be like matching on something and then in the default branch at the bottom matching on the same thing. That's a wierd thing to do.
to be clear, I'm not saying the syntactic idea is necessarily an unreasonable one, I just want to share that the emotional part of this doesn't resonate with me
like "we must find a way to get else if out of the language!" is just a hard movement for me to get excited about :sweat_smile:
Presumably if people understood the structure of the if (or when is as they would be alike) they wouldn't even be inclined to do that.
but have you ever considered trying to match on the same thing in the final branch of an when ..is structure.
if you have that when is like structure in front of you, you wouldn't want to do that.
It's not that we have to get rid of else if we're just providing something that has several benifits over else if.
Richard Feldman said:
to be clear, I'm not saying the syntactic idea is necessarily an unreasonable one, I just want to share that the emotional part of this doesn't resonate with me
This solves:
else if pushes the condition five characters past the ideal of having vertical alignment of all the conditions in an if..else if block. So that breaks the flow when visually scanning the conditions vertically.and has the benifits:
Matthias Toepp said:
Aside from solving the visual issues with
else..ifthis syntax has the positive side effects of:
reduced typing over a multi-branched
if..else
- When typing the structure out, at every branch this syntax permits immediate entry of either another condition or the final
elseas the last condition. whereas in a multi-branchif..elsethat's not true.it leads naturally to the pleasing (?) syntax of
elsebeing overloaded to have a similar meaning which can displace_ ->forwhen..is(as illustrated in the last example above. Obviously this is non-essential if not desired. This use ofelsein thewhen..isstructure could widely be seen as actually normalizing thewhen..isto more conventional syntax. Which would actually (in that regard, undo some of roc's "strangeness budget" spending.- It enhances the harmony of the language syntax, making the syntax for the two branching structures seem more like they belong together and making roc an even more consistent language.
I think that's about the best I can do to promote this...
In regard to the leading repeated if syntax, which other people seem to like, and which does solve all (what I see as minor/manageable) challenges with the syntax I've introduced ... That's not the syntax I immediately prefer but if people actually love it I will learn to love it too. It does solve all the challenges I'm trying to address and the disadvantages of my proposed syntax (which relate to added indentation and spacing, see this thread).
If the proposed change were impemented, writing else if would be unnecessary and would have the equivalent sillyness of writing:
when x is
Small ->
"small"
Large ->
"large"
_ -> when x is
VeryLarge ->
"very large"
...and for the same reason, the syntax would lead people to add branches in the easiest way.
People would hopefully never want to write that since they would have a kind of branching by default with the proposed syntax just as when..is has.
Thanks to everyone who gave their perspectives on this! :smile:
I would also just let the else if be fixed by the formatter (roc format) and not error or warn on compiling.
If you just want your code to compile you can technically write horribly formatted roc but instead of printing a bunch of errors and warnings on compile we allow users to just send It through the formatter to fix it.
Sounds great! (One possible issue with the idea of having multiple ifs could be that if you're reading in the middle of a long series of ifs, you would need to go up all the way to the top of the file to be sure there's not another ifabove.)
I think you need to check the tabbing of the previous definition before the current if.
oh, you're saying you would require an indent at the start of an (multi) if? (i.e. one more indent than the current existing if..else..?
No, just that if you see
x = 32
x + y
if something then
...
This if would be an else if
Actually...hmm..that may not always be true, I guess it could be:
z =
x = 32
x + y
if something then
...
So yeah, would have to scroll up to see the if before to guarantee it wasn't a nested definition before an if.
But you only have to scroll up until you see the definiton of z. that would then mean it can't be an else if
I think in general this wouldn't be a real issue
@Richard Feldman (Tongue in cheek) I just realized... we could also go in the opposite direction and change when..is to require prefixes to reduce the indentation it requires and limit each instance of the structure to two branches so people would have to chain the structures together in order to get multiple branches! :grinning_face_with_smiling_eyes:
Matthias Toepp said:
If the proposed change were impemented, writing
else ifwould be unnecessary and would have the equivalent sillyness of writing:when x is Small -> "small" Large -> "large" _ -> when x is VeryLarge -> "very large"...and for the same reason, the syntax would lead people to add branches in the easiest way.
People would hopefully never want to write that since they would have a kind of branching by default with the proposed syntax just as
when..ishas.
I see what you're saying, but I don't think it would be quite the same level of silliness as that. With the when...isexample, you're giving up the compiler's exhaustiveness checking, right? With else if, it would just be a style issue.
But I see what you mean that in both cases, it would be using two nested constructs when only one is necessary
(deleted)
if x < 10 then
"..."
if x < 100 then
"..."
else
"..."
Does someone want to write up a brief document with some side-by-side comparisons with old syntax and major pros and cons? For the side-by-side I think we should compare a basic case, medium complex case and a realistic multi-level nested case.
If indentation is a concern why not just have roc format do something like this?
if x < 10 then
"..."
else if x < 100 then
"..."
else
"..."
I know it looks a little weird, but it seems less weird to me than trying to pretend that we can't nest an if expression in an else expression.
Alternatively, maybe the Roc editor could just display the if and else if as the same width by widening the former a bit and compressing the latter a bit.
if if can be syntax sugar for else if, how would I tell whether an if I'm looking at means if or else if? I see this as a concrete downside to the syntax sugar approach.
If we go with the approach of making if expressions more closely resemble when ... is expressions, we still have an else branch. That else branch can either
a) contain any expression, including another if, which would allow the else if we were trying to avoid, or
b) contain any expression except for an if, which could be confusing. How would we explain this when someone asks why?
I agree that aligning the boolean expressions in an if ... else has value, but I think there are other ways to achieve that goal that we could explore.
that we can't nest an if expression in an else expression
You can still nest an if in an else but the formatter would re-write "else if" as "if".
Alternatively, maybe the Roc editor could just display [...]
Displaying things how you like in the editor will be supported but there is merit to having it look nice in all cases (other editors, github...)
how would I tell whether an if I'm looking at means if or else if? I see this as a concrete downside to the syntax sugar approach.
This has been discussed earlier in this topic.
If indentation is a concern why not just have roc format do something like this?
It's an option but I've never seen anything like it in any programming language. It has reasonable trade-offs though.
Implementing Bryce's suggestions would require the least effort compared to other proposals. It's growing on me :)
Definitely agree that it would be good for the code to look nice everywhere, as much as is feasible. Just not convinced the syntax change is the best way to achieve that :). For my money it would cause more confusion than it’s worth.
But I’ll be the first to admit I don’t really care a lot about the conditional syntax compared to other Roc features. I’m excited about Roc because of the type system, the performance, Abilities, etc. Changing the conditional syntax won’t change that for me.
I suspect that choosing the very best syntax for conditionals won’t incentivize programmers to use Roc over alternatives. I think they’ll be attracted by some of the same things that caught my eye.
BUT: I haven’t spent hours of my life debugging a complex conditional. So maybe I’m just not in tune with the pain points.
I suspect that choosing the very best syntax for conditionals won’t incentivize programmers to use Roc over alternatives. I think they’ll be attracted by some of the same things that caught my eye.
I agree, we're trying to make a net improvement to the language, not a key feature.
ef is still my personal favorite though:
if x < 10 then
"..."
ef x < 100 then
"..."
else
"..."
anyway I'll write up a summary of this discussion once I'm done with PR#5324
Personally I think none of this is big enough to be worth changing. I definitely don't think it is big enough to add an extra keyword.
If we change to
If x < 10 then
...
If x < 100 then
...
else
...
I personally don't expect being in an else if to be hard to figure out. It also, would be no worse than the semi common structure in other languages of not using else if if you're returning in the previous branch. Though generally this is used for error cases or similar. Less common for any random if.
if (x < 10) {
...
return ...;
}
if (x < 100)
return ...;
return ...;
If figuring out you are in an else if ends up being a pain point, we can always call it a failed experiment and change back.
That's my current opinion after all of the discussion.
Note: when i say "big enough to be worth changing", I mean that from my perspective, these proposals don't have enough benefits to justify changing away from a status quo that will be super familiar to most programmers and frictionless to learn.
The proposal from Bryce has no real penalty in familiarity or friction when learning.
If it is just done by the formatter, I guess not. Though I guess that would mostly be the same with else if to if proposal (just would add friction in reading someone else code and a bit of understanding, not in writing for the first time though).
All that said, at least currently, I dislike how Bryce's proposal reads.
also a downside in general of formatters trying to align things like that is that they can create a lot of git diff noise
which maybe is a tradeoff worth accepting, but it's a downside; it's not like it's just free
All of these are stable, right? So they would be a one time diff just like any other formatting. So I don't think it would really add git diff noise.
It could introduce diff noise if you add an else if to a condition that previously only had an if and else.
Subjectively, I don’t much like the way my proposed formatting looks either. I was just trying to think of ways to achieve the vertical alignment without incurring the costs associated with the alternative syntax suggestions. Didn’t think about the git diff issue!
I personally wouldn’t want to trade diff stability for vertical alignment. ¯\_(ツ)_/¯
You technically could have diff stability and the vertical alignment if you always formatted if even if it didn't have an else if, that said, It would look even worse:
if x < 10 then
"..."
else
"..."
I think most users would think that was a bug in the formatter.
Yeah, I don’t like that either.
In case it wasn’t clear, I favor leaving the syntax as-is. The downsides of changing it outweigh the benefit of vertical alignment for me, by a fair margin. My suggestions are just an attempt at compromise I guess?
yeah that's how I feel too
Anton has marked this topic as resolved.
Last updated: Jun 16 2026 at 16:19 UTC