Ever since I started programming with Pascal I wondered about the IF construct, specifically the two-keywords ELSE IF construct for elseif blocks. Most languages use one keyword for it, usually something like ELSEIF or ELSIF.
The curious Pascal construct probably goes back to the late 60s / early 70s, when the language was first designed.
So why did Wirth choose this specific language design? When studying/developing a compiler one will see the benefit (and beauty) of it, especially when considering the available hardware at the time. In order to make a compiler fast and (relatively) simple, it should be top-down and do a single pass. But with ELSEIF blocks there is no way to know how many blocks there are, which means there is also no way to know what label to branch out to, unless the compiler does a second pass.
But with Wirth's clever ELSE IF construct, a fixed branch-out label can be set as soon as the parser finds the ELSE keyword. It doesn't matter how many ELSE IF's will follow; they either jump to the next ELSE IF (if the condition is false) or they branch out to the fixed label. The only price to pay is a redundant label if the final ELSE IF block is not followed by a ELSE block.
Only Basic I guess. it is a not natural combination of two keywords that already are in use. Probably they needed to fix something, but I'm not so deep into Basic details. That said, later compilable basics are not original BASIC, so it might not even be part of the original Basic syntax. Afaik C=64 Basic V2 only had if and goto.
If the IF block is simple. You still need to cater for a lot of complexity if the part before the ELSE is very complex, or handle it recursively.Recursive processing is key. Once the statements are well defined and blocks are handled properly, (deep) nesting will not be a problem.
Most conditional branches have very limited distances they can jump, so it nearly never this simple.
if
<condition>
BEQ L0
a
BSR fnA
LEA a(PC), A0
MOVE D0, (A0)
if
<condition>
BEQ L1
a
MOVE #0, D0
LEA a(PC), A0
MOVE D0, (A0)
end
L1:
end
BRA L2
L0:
<condition>
BEQ L3
fnB
BSR fnB
end
BRA L2
L3:
<condition>
BEQ L4
fnC
BSR fnC
end
BRA L2
L4:
<condition>
BEQ L5
fnD
BSR fnD
end
BRA L2
L5:
fnZ
BSR fnZ
end
L2:
EOI
Well, Pascal is not that simple, compare:
if a then if b then s else s2 with if a then if b then s; else s2
I tried to illustrate the difference with indentation (which the compiler of course ignores)
Ever since I started programming with Pascal I wondered about the IF construct, specifically the two-keywords ELSE IF construct for elseif blocks. Most languages use one keyword for it, usually something like ELSEIF or ELSIF.It's a bit amusing to see the Pascal if/then/else construct described as "curious".
The curious Pascal construct probably goes back to the late 60s / early 70s, when the language was first designed.
It's a bit amusing to see the Pascal if/then/else construct described as "curious".I wasn't referring to " IF..THEN.ELSE" but to "ELSE IF". Python and PHP are widely used and support exactly this "poor" ELIF and ELSEIF design. I wouldn't call it poor per se, but from a compiler development point of view it requires more steps only to satisfy potential programmers' preference. As far as I can trace it back, the ELSEIF clause was introduced in the 1980s (at least with QuickBASIC) when computers became more powerful and back tracking and 2-pass techniques became acceptable techniques.
In a language that has the if/else construct, an "elseif", or any other syntactic variant thereof, is an indication of poor language design. First, it's completely redundant/unnecessary. Second, imagine if there was an "elsefor" or "elsewhile", etc, that would legitimately be "curious". An "elseif" construct is as curious as any of those yet, programmers don't see it that way because it allows them to indulge in one of their most common poor programming practices, that is, deeply nested if/else constructions. A very poor programming habit made even worse by the "preference" some programmers have not to align begin/end pairs.
"elseif"/"elsif" is simply "cheap design" that caters to poor programming.
So I know that plenty of people are going to object to my saying this, but Pascal's syntax is a mess.I partially agree. But regarding the two-keywords ELSE IF construct, it is found in leading programming languages, and from a compiler construction point of view, it is logical. This is exactly the reason why every serious programmer should know at least SOMETHING about compiler design.
I wasn't referring to " IF..THEN.ELSE" but to "ELSE IF".I see what you're saying now. I guess/believe that Wirth chose the "ELSE IF" syntax because things like "elseif"/"elif" are redundant when there is "IF" and "ELSE".
So I know that plenty of people are going to object to my saying this, but Pascal's syntax is a mess.I'd say its got a few quirks but, I wouldn't describe the Pascal syntax as a mess. Unlike in other languages, some very popular ones, there are very few ways in Pascal of messing things up due to a syntactically unintended construct.
I guess/believe that Wirth chose the "ELSE IF" syntax because things like "elseif"/"elif" are redundant when there is "IF" and "ELSE".
I partially agree. But regarding the two-keywords ELSE IF construct, it is found in leading programming languages, and from a compiler construction point of view, it is logical. This is exactly the reason why every serious programmer should know at least SOMETHING about compiler design.
I'd say its got a few quirks but, I wouldn't describe the Pascal syntax as a mess. Unlike in other languages, some very popular ones, there are very few ways in Pascal of messing things up due to a syntactically unintended construct.
The original Wirth syntax said:Nice :)
After every then or else is exact one statement allowed. If there are more then one statement you have to enclose them with begin ... end;
So this is allowed:
If c = clBlue then doSomeThing else if c = clLime then doAnotherThing else if c = clRed then PaintItRed else begin MixedColors; canvas.TextOut (10,10,'Mixed Colors'); end;
Winni
This discussion about the chained if/else reminded me of how nicely that construct is implemented in COBOL85 and above.
In COBOL a programmer can simply havefully linear and prioritized by the test sequence. In addition to that, it allows multiple conditions to be tested making the implementation of logical tables simple and really easy to understand and maintain. It's also possible to evaluate against FALSE, which can occasionally be very convenient.
EVALUATE TRUE WHEN <conditional expression 1> <statements applicable to above condition> WHEN <conditional expression 2> <statements applicable to above condition> WHEN <conditional expression n> <statements applicable to above condition> WHEN OTHER <statements applicable to above condition> END-EVALUATE
That statement can easily be synthesized in Pascal using a nested procedure (or nested function if convenient) but, it is extremely rare to see it done that way. Instead, long series of "else if" are all too common.
I wouldn't recommend synthesizing such construct using procedures because it would be much less optimal with the added stack frames. Elegance is nice but not at the cost of less optimal code.You're right in that there is an added stack frame in that case but, the loss of performance is negligible and, only perceptible if the procedure is executed extremely often.
Ever since I started programming with Pascal I wondered about the IF construct, specifically the two-keywords ELSE IF construct for elseif blocks. There are languages that use one keyword for it (VisualBASIC, Python, PHP), usually something like ELSEIF or ELSIF.It's rather simple: Pascal does not have an ELSE IF construct. It simply has another if ... then (... else) statement inside the else-branch of an if-statement (or the then-branch). This reduces complexity in the parser, cause then it's just a chain of if-statements.
Ever since I started programming with Pascal I wondered about the IF construct, specifically the two-keywords ELSE IF construct for elseif blocks. There are languages that use one keyword for it (VisualBASIC, Python, PHP), usually something like ELSEIF or ELSIF.It's rather simple: Pascal does not have an ELSE IF construct. It simply has another if ... then (... else) statement inside the else-branch of an if-statement (or the then-branch). This reduces complexity in the parser, cause then it's just a chain of if-statements.
Pascal has case....but a case statement cannot be used to replace an if/else chain.
Nested case statements can replace an if/else chain, and are usually clearer, if more verbose.Pascal has case....but a case statement cannot be used to replace an if/else chain.
Nested case statements can replace an if/else chain, and are usually clearer, if more verbose.I don't see how it could be done when the if statements compare an expression to another expression. A case statement requires an expression to be compared with constant values. I don't see how that limitation can be circumvented even with nested case statements.
One slight advantage of case over if/then/else is that when repeated millions of times for the same operation, case is usually slightly faster.Yes, because in the example you showed the compiler can create a jump table based on the variable's value but, a jump table can only be created when a single expression is compared against constants. That's one of the very significant limitations of the case statement, the inability to compare one expression against another.
In VB i could do this:
Select Case True
Case a=1
DoSomething1
Case b=3
DoSomethingElse
Case Else
KABOOM
End Select
Is there an equivalent in Pascal?
In VB i could do this:Would this fit the bill?
Select Case True
Case a=1
DoSomething1
Case b=3
DoSomethingElse
Case Else
KABOOM
End Select
Is there an equivalent in Pascal?
The original Wirth syntax said:
After every then or else is exact one statement allowed. If there are more then one statement you have to enclose them with begin ... end;
But at some point before the ALGOL-68 standardisation process it was recognised that that syntax, no matter how elegant, was also susceptible to the dangling-else problem... note that I'm not calling it an ambiguity, but it's definitely a problem.It's not a "problem", it is a consequence of the language not requiring explicit statement terminators for some constructs, e.g, if <statements> fi, or case <statements> esac. The lack of explicit statement terminators is what causes the dangling else "problem".
he introduced records etc. which had an explicit end, rather than themselves needing a begin...end pair. In short, whatever his reputation as a pragmatist, Pascal's syntax is messily inconsistent.There is no inconsistency, what there is, is the elimination of superfluous syntactic elements. "record", "repeat" or "case" do not need begin/end pairs because they are by design <field>/<statement> containers, therefore requiring begin/end pairs in those statements would be superfluous and only add unnecessary clutter to the language.
So I'm sorry, but whatever the efforts of people over the years Pascal as defined by Wirth was flawed.Every design has its own set of implications, that doesn't mean the design is flawed (though in some cases, it could.)
But at some point before the ALGOL-68 standardisation process it was recognised that that syntax, no matter how elegant, was also susceptible to the dangling-else problem... note that I'm not calling it an ambiguity, but it's definitely a problem.It's not a "problem", it is a consequence of the language not requiring explicit statement terminators for some constructs, e.g, if <statements> fi, or case <statements> esac. The lack of explicit statement terminators is what causes the dangling else "problem".
The Pascal language is very well designed.
But even though it's not a syntactic ambiguity, it is undoubtedly a problem in that it allows an inattentive (aka busy) or inexperienced user to write code which doesn't behave as he intended.
[Statement terminators are not necessary for if <cond> then <block> [else <block>] simply because the block already is terminated with END. Then the else option is just one token lookahead.Pascal doesn't have statement terminators. It has statement separators, which is not the same (yes, quite confusing). IMO statement terminators serve a better purpose in that they make it clear where a statement starts and where it ends, especially with (nested) IF blocks. Because in Pascal the semicolon is used as a statement separator, it often leads to null statements because (even experienced) programmers use it where it is not required. That is one issue I would like to tackle in a new Pascal-like language; it shouldn't leave any room for ambiguity.
However, we have to bear in mind the time that the language was developed. Compiler construction was in its infancy and over time significant and important improvements were implemented in successive languages that borrowed from the early greats such as Pascal. And here we touch upon the reason for developing new languages as the old ones almost always stick to their early definitions and rarely undergo syntax improvements that could lift them to modern standards.
Apart from nesting: no. But there are other options that are overlooked here.Pascal has case....but a case statement cannot be used to replace an if/else chain.
Interesting.Apart from nesting: no. But there are other options that are overlooked here.Pascal has case....but a case statement cannot be used to replace an if/else chain.
Consider:Since i is here not a loop variable, but a plain ordinal, it is even allowed to modify it.
var i:integer = 0; begin if i in [0..3, 7, 9, 12..15] then { do something }; end.
You can use this to construct C like switch w/o breaks for example.