39
$\begingroup$

In C, else if is nothing but a new if statement after a single-statement else clause. Why do languages like Python and Ruby have a dedicated construct for elsif/elif?

$\endgroup$

6 Answers 6

36
$\begingroup$

They do this to avoid the dangling else problem.

In many programming languages, the syntax for else-if statements is ambiguous. For example, consider the following C program:

if(a) if (b) x++; else y++;

Which if should the else belong to? Is it the inner one?

if (a)
    if (b)
        x++;
    else
        y++;

or the outer one?

if (a)
    if (b)
        x++;
else
    y++;

This ambiguity is known as the "dangling else problem". One way that programming languages can avoid it is to require delimiters around the "then" and the "else" part of the if. Some languages, such as Swift, mandate that there must be curly braces:

if (a) {
   x++;
} else {
   y++;
}

Some languages instead use then and end keywords, for a similar effect. For example, Lua:

if a then
   x = x + 1
else
   y = y + 1
end

However, if our language requires these delimiters around the else then we cannot write else if as we do in C. Because else must be followed by an open curly brace, we would end up with open braces between the else and the if, and a long sequence of closing delimiters at the end.

if (a) {
    x++;
} else { if (b) {
    y++;
} else { if (c) {
    z++;
} else {
    w++;
}}} /*ouch!*/

Having an elseif keyword is an elegant way to avoid this }}} avalanche. We can still mandate braces after if and else, but there aren't those pesky braces between the two

Swift and Rust avoid the else { if problem by special casing the else if. Their grammar says that the next token after the else must be a {, unless it's an if. This is certainly a valid way to solve the problem and avoids creating a new keyword. That said, the programmer must be aware that else if is a special case. If one is used to languages with traditional if-else syntax, they might expect they are allowed to write to substitute any other statement in place of the if statement in the else if. In languages with elseif this question doesn't come up because it's loud and clear that elseif is special.

$\endgroup$
8
  • 1
    $\begingroup$ PHP is a clike just like C and JS, and it has elseif. I wonder what the reason is there, maybe to save the keystroke. $\endgroup$
    – naffetS
    Commented May 19, 2023 at 3:23
  • 6
    $\begingroup$ The dangling else problem doesn't contain any occurrences of else if, and would still occur in C's grammar if elseif were to be written instead. The point about block delimiters is reasonable, but I think it would be clearer if this answer said that it's a consequence of requiring delimiters around if and else blocks, which is done in part to avoid the dangling else problem but also for other reasons (hence such languages also tend to require block delimiters for loops, try/catch, and so on). $\endgroup$
    – kaya3
    Commented May 19, 2023 at 9:58
  • 2
    $\begingroup$ Also technically the dangling else problem could also be solved by only requiring braces around the if body, and not necessarily also the else body, which would allow else if to still be written. Though this might seem inconsistent to users of the language. $\endgroup$
    – kaya3
    Commented May 19, 2023 at 10:00
  • 5
    $\begingroup$ In Python, the dangling else problem is avoided by significant indentation, which is analogous to mandating braces around the if/else body. Python's elif allows if-else-if without having to nest the elses in increasingly deeper levels of indentation (which would be analogous to the }}} problem discussed in my answer). $\endgroup$
    – hugomg
    Commented Jul 2, 2023 at 14:25
  • 2
    $\begingroup$ More specifically, the programmer is likely to write the second version, and their use of indentation may think it will work as they expect, but it will actually be parsed as the first version. This is similar to what happens when they write a braceless if or else and later add a second statement without adding braces. $\endgroup$
    – Barmar
    Commented Feb 20 at 21:22
23
$\begingroup$

The way the chaining of else if blocks is defined in C follows naturally from the way the grammar allows for braceless blocks:

if (x) {
} else if (y) {
}

being parsed the same as

if (x) {
} else
    if (y) {
    }

i.e.

if (x) {
} else {
    if (y) {
    }
}

When you allow for such constructs in the syntax, a dedicated keyword is useless.

On the other hand, if you take Python, for example, since blocks are defined by indentation (and not by enclosing tokens such as braces), this is not valid out-of-the-box (you have to special-case it, whereas in C it was "free"):

if x:
    pass
else if y:
    pass

So, given that we're forced to create that special case, it makes sense to choose something shorter than else if, hence elif (or elsif).

$\endgroup$
16
$\begingroup$

Another reason for elseif/elsif/elif is if the conditional construct has a keyword terminator, like the shell's fi or Lua's end. You don't want to be writing else if because now you're writing nested if's, which have to be terminated with a whole sequence of repeated end tokens.

$\endgroup$
1
  • $\begingroup$ That is the reason I added ElseIf to AEC (my programming language). $\endgroup$ Commented Jul 4, 2023 at 13:32
13
$\begingroup$

They need one

In C-style languages like JS, you can put a single statement after an if to run just that one:

if (x == 1) print("x is 1!");

In fact, else if isn't even necessarily interpreted specially by the compiler. It could just be parsed as an if statement directly following the else.

However, in languages like Python where you can't do this, it would be natural to have a keyword specifically for else-if since you don't get that for free.

$\endgroup$
2
  • 2
    $\begingroup$ There are languages that have "else if" as separate words but do not allow a single expression after if (like Rust) $\endgroup$
    – mousetail
    Commented May 16, 2023 at 17:25
  • $\begingroup$ @mousetail That's true, I was going to touch on how it's possible to detect an else if even without that, might come back and do that in a sec $\endgroup$ Commented May 16, 2023 at 18:06
4
$\begingroup$

else if could never be an invalid construct in any reasonable language.

Languages that also use elseif tend to have enforced grouping constructs. That is, you cannot omit the braces or equivalents after the if conditions. In many cases it's because the language is using specific grouping constructs for every control structure, that is, if...endif, for...endfor. In other cases it's because grouping is an important part of the grammar, for example in Python and Tcl.

In these cases, if you don't use elseif, a long conditional statement would become:

if(...)
    ...;
else
    if(...)
        ...;
    else
        if(...)
            ...;
        else
            ...;
        endif;
    endif;
endif;

which stacks many endifs at the end and is not very practical.

There are languages like PHP, where grouping constructs are not enforced, but also have elseif. Many people choose to use else if anyway, and some may not even realize elseif existed. So your design decisions may not matter that much, after all.

There are also languages like the LISP variants. Everybody already knows that code in them would always have this problem everywhere, so nobody cares about the little more problems caused by not having elseif with enforced grouping constructs.

$\endgroup$
0
$\begingroup$

elseif/elsif/elif is shorter, which is important in Code Golf.

$\endgroup$
1
  • $\begingroup$ There are much terser ways to write if-else-chains than by adding the elif keyword. Even in C you'd write something like a?b:c?d:e?…. $\endgroup$
    – G. Sliepen
    Commented Feb 19 at 18:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .