Magical Tomato
Magical Tomato

Reputation: 101

Short Circuit evaluation in Pascal

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

Answers (2)

Kai Burghardt
Kai Burghardt

Reputation: 1572

The notion of short-circuit evaluation is not part of the language:

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.

Therefore, you need to consult your compiler’s documentation.

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.

Pascal “likes” writing things out.

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 and or_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 value true; the term shall denote the value false if the left operand denotes the value false; otherwise, the term shall denote the value denoted by the right operand. In a simple‑expression of the form A or_else B, the right operand shall be evaluated if and only if the left operand denotes the values false; the simple-expression shall denote the value true if the left operand denotes the value true; 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).

Experimentally determining your compiler’s behavior.

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 functions with side-effects, particularly writeLns, 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

D&#250;thomhas
D&#250;thomhas

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.

http://tpcg.io/_HUNS7P

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

Related Questions