Reputation: 101
I am trying to see how to test short circuit evaluation in Pascal but not sure if doing it correctly. This is what I have so far.
program shortcircuit;
var
{ local variable definition }
a : integer;
b : integer;
begin
a := 8;
b := 0;
if( (b <> 0) and (a / b) ) then
(* if condition is true then print the following *)
writeln('...' )
end.
Upvotes: 2
Views: 391
Reputation: 1572
Boolean expressions have the property that their value may be known before the entire expression has been evaluated. Assume for example, that
X = 0
. Then the value of the expression(x > 0) and (X < 10)
is already known to be false after computation of the first factor, and the second need not be evaluated. Whether or not the second factor is evaluated is implementation-dependent. This means that you must assure that the second factor is well defined, independent of the value of the first factor. […]
Source: Jensen, Kathleen; Wirth, Niklaus. Pascal – user manual and report (4th revised ed.). p. 32. doi:10.1007/978‑1‑4612‑4450‑9. ISBN 978‑0‑387‑97649‑5.
Delphi and the FreePascal Compiler have the {$B+}
/{$boolEval on}
and {$B‑}
/{$boolEval off}
(default) compiler directives, disabling and enabling short-circuit evaluation respectively.
The GNU Pascal Compiler recognizes {$B+}
/{$B‑}
too, plus {$short‑circuit}
/{$no‑short‑circuit}
.
However, the default is not to guarantee either, I don’t know, maybe for some SIMD optimizations.
Because, or if this implementation-dependence is dissatisfying or unwanted, the ISO standard 10206 “Extended Pascal” introduces two other Boolean operators:
A primary, a factor, a term, or a simple‑expression shall be designated an operand. Except for the
and_then
andor_else
operators, the order of evaluation of the operands of a dyadic operator shall be implementation-dependent.NOTE — This means, for example, that the operands may be evaluated in textual order, or in reverse order, or in parallel, or they may not both be evaluated.
6.8.3.3 Boolean operators
[…] In a term of the form
A and_then B
, the right operand shall be evaluated if and only if the left operand denotes the valuetrue
; the term shall denote the valuefalse
if the left operand denotes the valuefalse
; otherwise, the term shall denote the value denoted by the right operand. In a simple‑expression of the formA or_else B
, the right operand shall be evaluated if and only if the left operand denotes the valuesfalse
; the simple-expression shall denote the valuetrue
if the left operand denotes the valuetrue
; otherwise, the simple-expression denotes the value denoted by the right operand.
Unfortunately, of the previously mentioned compilers only the GNU Pascal Compiler supports and_then
/or_else
.
Generally speaking, if you want “short-circuit evaluation”, you have to write it out in Pascal (e. g. a nested if
in lieu of and_then
).
I am trying to see how to test short circuit evaluation in Pascal but not sure if doing it correctly.
A test design would use Boolean
function
s with side-effects, particularly writeLn
s, like so:
program shortCircuitTest(output);
function A: Boolean;
begin
writeLn('A');
A := false;
end;
function B: Boolean;
begin
writeLn('B');
B := true;
end;
{ === MAIN ========= }
begin
if A and B then
begin
writeLn('then branch');
end
else
begin
writeLn('else branch');
end;
end.
However, this is only an indicator. You really need to consult your compiler’s documentation to know the details.
Upvotes: 2
Reputation: 10083
It is unclear what your question is, but you should try to provide a program that actually compiles before posting. This will help you answer your own questions.
The first problem you have is that Pascal has no concept of automatically convert to boolean that many C-derived languages do. You must test the inequity with zero explicitly.
I would also add an else
clause to print when your test works successfully.
var
{ local variable definition }
a : integer;
b : integer;
begin
a := 8;
b := 0;
if( (b <> 0) and ((a / b) <> 0.0) ) then
(* if condition is true then print the following *)
writeln('fooey' )
else writeln('short circuited')
end.
It is possible, should you make some minor modifications to the LHS of the and
expression, that the compiler will notice you are hard-coding an attempt to divide by zero and complain.
Finally, Pascal always does short-circuit evaluation by default. You can disable it with a compiler directive, but that is always The Wrong Thing To Do.
For your example (avoiding a divide by zero error), the code will do the correct thing by default.
if (b <> 0) and some_predicate_function( a / b ) then ...
Though if you are just doing a checked divide, you could just make yourself a useful function that defaults to an acceptable value:
function checked_divide( a,b:integer; fooey:double = 0.0 ) : double;
begin
if b <> 0
then result := a / b
else result := fooey
end;
Upvotes: 2