Short-circuit evaluation: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 160: Line 160:
a=T, b=T, T ANDTH T = T
a=T, b=T, T ANDTH T = T
</pre>
</pre>
=={{header|C}}==
Boolean operators &amp;&amp; and || are shortcircuit operators.

<lang c>#include <stdio.h>
#include <stdbool.h>

bool a(bool in)
{
printf("I am a\n");
return in;
}

bool b(bool in)
{
printf("I am b\n");
return in;
}

#define TEST(X,Y,O) \
do { \
x = a(X) O b(Y); \
printf(#X " " #O " " #Y " = %s\n\n", x ? "true" : "false"); \
} while(false);

int main()
{
bool x;

TEST(false, true, &&); // b is not evaluated
TEST(true, false, ||); // b is not evaluated
TEST(true, false, &&); // b is evaluated
TEST(false, false, ||); // b is evaluated

return 0;
}</lang>

=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
<lang csharp>using System;
<lang csharp>using System;
Line 219: Line 255:
a
a
True or True = True</lang>
True or True = True</lang>

=={{header|Clojure}}==
=={{header|Clojure}}==
The print/println stuff in the doseq is kinda gross, but if you include them all in a single print, then the function traces are printed before the rest (since it has to evaluate them before calling print).
The print/println stuff in the doseq is kinda gross, but if you include them all in a single print, then the function traces are printed before the rest (since it has to evaluate them before calling print).

Revision as of 19:36, 16 November 2010

Task
Short-circuit evaluation
You are encouraged to solve this task according to the task description, using any language you may know.

Assume functions a and b return boolean values, and further, the execution of function b takes considerable resources without side effects, and is to be minimised.

If we needed to compute:

   x = a() and b()

Then it would be best to not compute the value of b() if the value of a() is computed as False, as the value of x can then only ever be False.

Similarly, if we needed to compute:

   y = a() or b()

Then it would be best to not compute the value of b() if the value of a() is computed as True, as the value of x can then only ever be True.

Some languages will stop further computation of boolean equations as soon as the result is known, so-called short-circuit evaluation of boolean expressions

Task Description
The task is to create two functions named a and b, that take and return the same boolean value. The functions should also print their name whenever they are called. Calculate and assign the values of the following equations to a variable in such a way that function b is only called when necessary:

   x = a(i) and b(j)
   y = a(i) or  b(j)

If the language does not have short-circuit evaluation, this might be achieved with nested if statements.

Ada

Ada has built-in short-circuit operations and then and or else: <lang Ada> with Ada.Text_IO; use Ada.Text_IO;

procedure Test_Short_Circuit is

  function A (Value : Boolean) return Boolean is
  begin
     Put (" A=" & Boolean'Image (Value));
     return Value;
  end A;
  function B (Value : Boolean) return Boolean is
  begin
     Put (" B=" & Boolean'Image (Value));
     return Value;
  end B;

begin

  for I in Boolean'Range loop
     for J in Boolean'Range loop
        Put (" (A and then B)=" & Boolean'Image (A (I) and then B (J)));
        New_Line;
     end loop;
  end loop;
  for I in Boolean'Range loop
     for J in Boolean'Range loop
        Put (" (A or else B)=" & Boolean'Image (A (I) or else B (J)));
        New_Line;
     end loop;
  end loop;

end Test_Short_Circuit; </lang> Sample output:

 A=FALSE (A and then B)=FALSE
 A=FALSE (A and then B)=FALSE
 A=TRUE B=FALSE (A and then B)=FALSE
 A=TRUE B=TRUE (A and then B)=TRUE
 A=FALSE B=FALSE (A or else B)=FALSE
 A=FALSE B=TRUE (A or else B)=TRUE
 A=TRUE (A or else B)=TRUE
 A=TRUE (A or else B)=TRUE

ALGOL 68

With Standard

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

Note: The "brief" conditional clause ( ~ | ~ | ~ ) is a the standard's shorthand for enforcing short-circuit evaluation. Moreover, the coder is able to define their own proc[edures] and op[erators] that implement short-circuit evaluation by using Algol68's proceduring. <lang algol68>PRIO ORELSE = 2, ANDTHEN = 3; # user defined operators # OP ORELSE = (BOOL a, PROC BOOL b)BOOL: ( a | a | b ),

  ANDTHEN = (BOOL a, PROC BOOL b)BOOL: ( a | b | a );
  1. user defined Short-circuit_evaluation procedures #

PROC or else = (BOOL a, PROC BOOL b)BOOL: ( a | a | b ),

    and then = (BOOL a, PROC BOOL b)BOOL: ( a | b | a );

test:(

 PROC a = (BOOL a)BOOL: ( print(("a=",a,", ")); a),
      b = (BOOL b)BOOL: ( print(("b=",b,", ")); b);

CO

  1. Valid for Algol 68 Rev0: using "user defined" operators #
  2. Note: here BOOL is being automatically "procedured" to PROC BOOL #
 print(("T ORELSE F = ", a(TRUE) ORELSE b(FALSE), new line));
 print(("F ANDTHEN T = ", a(FALSE) ANDTHEN b(TRUE), new line));
 print(("or else(T, F) = ", or else(a(TRUE), b(FALSE)), new line));
 print(("and then(F, T) = ", and then(a(FALSE), b(TRUE)), new line));

END CO

  1. Valid for Algol68 Rev1: using "user defined" operators #
  2. Note: BOOL must be manually "procedured" to PROC BOOL #
 print(("T ORELSE F = ",  a(TRUE) ORELSE  (BOOL:b(FALSE)), new line));
 print(("T ORELSE T = ",  a(TRUE) ORELSE  (BOOL:b(TRUE)), new line));
 print(("F ANDTHEN F = ", a(FALSE) ANDTHEN (BOOL:b(FALSE)), new line));
 print(("F ANDTHEN T = ", a(FALSE) ANDTHEN (BOOL:b(TRUE)), new line));
 print(("F ORELSE F = ",  a(FALSE) ORELSE  (BOOL:b(FALSE)), new line));
 print(("F ORELSE T = ",  a(FALSE) ORELSE  (BOOL:b(TRUE)), new line));
 print(("T ANDTHEN F = ", a(TRUE) ANDTHEN (BOOL:b(FALSE)), new line));
 print(("T ANDTHEN T = ", a(TRUE) ANDTHEN (BOOL:b(TRUE)), new line))

)</lang> Output:

a=T, T ORELSE F = T
a=T, T ORELSE T = T
a=F, F ANDTHEN F = F
a=F, F ANDTHEN T = F
a=F, b=F, F ORELSE F = F
a=F, b=T, F ORELSE T = T
a=T, b=F, T ANDTHEN F = F
a=T, b=T, T ANDTHEN T = T

With Extensions

Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

<lang algol68>test:(

 PROC a = (BOOL a)BOOL: ( print(("a=",a,", ")); a),
      b = (BOOL b)BOOL: ( print(("b=",b,", ")); b);
  1. Valid for Algol 68G and 68RS using non standard operators #
 print(("T OREL F = ",  a(TRUE) OREL  b(FALSE), new line));
 print(("T OREL T = ",  a(TRUE) OREL  b(TRUE), new line));
 print(("F ANDTH F = ", a(FALSE) ANDTH b(FALSE), new line));
 print(("F ANDTH T = ", a(FALSE) ANDTH b(TRUE), new line));
 print(("F OREL F = ",  a(FALSE) OREL  b(FALSE), new line));
 print(("F OREL T = ",  a(FALSE) OREL  b(TRUE), new line));
 print(("T ANDTH F = ", a(TRUE) ANDTH b(FALSE), new line));
 print(("T ANDTH T = ", a(TRUE) ANDTH b(TRUE), new line))

CO;

  1. Valid for Algol 68G and 68C using non standard operators #
 print(("T ORF F = ", a(TRUE) ORF b(FALSE), new line));
 print(("F ANDF T = ", a(FALSE) ANDF b(TRUE), new line))

END CO

)</lang> Output:

a=T, T OREL F = T
a=T, T OREL T = T
a=F, F ANDTH F = F
a=F, F ANDTH T = F
a=F, b=F, F OREL F = F
a=F, b=T, F OREL T = T
a=T, b=F, T ANDTH F = F
a=T, b=T, T ANDTH T = T

C

Boolean operators && and || are shortcircuit operators.

<lang c>#include <stdio.h>

  1. include <stdbool.h>

bool a(bool in) {

 printf("I am a\n");
 return in;

}

bool b(bool in) {

 printf("I am b\n");
 return in;

}

  1. define TEST(X,Y,O) \
 do {								\
   x = a(X) O b(Y);						\
   printf(#X " " #O " " #Y " = %s\n\n", x ? "true" : "false");	\
 } while(false);

int main() {

 bool x;
 TEST(false, true, &&); // b is not evaluated
 TEST(true, false, ||); // b is not evaluated
 TEST(true, false, &&); // b is evaluated
 TEST(false, false, ||); // b is evaluated 
 return 0;

}</lang>

C#

<lang csharp>using System;

class Program {

   static bool a(bool value)
   {
       Console.WriteLine("a");
       return value;
   }
   static bool b(bool value)
   {
       Console.WriteLine("b");
       return value;
   }
   static void Main()
   {
       foreach (var i in new[] { false, true })
       {
           foreach (var j in new[] { false, true })
           {
               Console.WriteLine("{0} and {1} = {2}", i, j, a(i) && b(j));
               Console.WriteLine();
               Console.WriteLine("{0} or {1} = {2}", i, j, a(i) || b(j));
               Console.WriteLine();
           }
       }
   }

}</lang> Output: <lang>a False and False = False

a b False or False = False

a False and True = False

a b False or True = True

a b True and False = False

a True or False = True

a b True and True = True

a True or True = True</lang>

Clojure

The print/println stuff in the doseq is kinda gross, but if you include them all in a single print, then the function traces are printed before the rest (since it has to evaluate them before calling print). <lang Clojure>(letfn [(a [bool] (print "(a)") bool)

       (b [bool] (print "(b)") bool)]  
 (doseq [i [true false] j [true false]]
   (print i "OR" j "= ")               
   (println (or (a i) (b j)))          
   (print i "AND" j " = ")             
   (println (and (a i) (b j)))))</lang>

Outputs:

true OR true = (a)true       
true AND true  = (a)(b)true  
true OR false = (a)true      
true AND false  = (a)(b)false
false OR true = (a)(b)true   
false AND true  = (a)false   
false OR false = (a)(b)false 
false AND false  = (a)false

D

From the first Python version. <lang d>import std.stdio: writefln, writeln;

T a(T)(T answer) {

   writefln("  # Called function a(%s) -> %s", answer, answer);
   return answer;

}

T b(T)(T answer) {

   writefln("  # Called function b(%s) -> %s", answer, answer);
   return answer;

}

void main() {

   foreach (i; [false, true])
       foreach (j; [false, true]) {
           writeln("\nCalculating: x = a(i) && b(j)");
           auto x = a(i) && b(j);
           writeln("Calculating: y = a(i) || b(j)");
           auto y = a(i) || b(j);
       }

}</lang> Output:

Calculating: x = a(i) && b(j)
  # Called function a(false) -> false
Calculating: y = a(i) || b(j)
  # Called function a(false) -> false
  # Called function b(false) -> false

Calculating: x = a(i) && b(j)
  # Called function a(false) -> false
Calculating: y = a(i) || b(j)
  # Called function a(false) -> false
  # Called function b(true) -> true

Calculating: x = a(i) && b(j)
  # Called function a(true) -> true
  # Called function b(false) -> false
Calculating: y = a(i) || b(j)
  # Called function a(true) -> true

Calculating: x = a(i) && b(j)
  # Called function a(true) -> true
  # Called function b(true) -> true
Calculating: y = a(i) || b(j)
  # Called function a(true) -> true

E

E defines && and || in the usual short-circuiting fashion.

<lang e>def a(v) { println("a"); return v } def b(v) { println("b"); return v }

def x := a(i) && b(j) def y := b(i) || b(j)</lang>

Unusually, E is an expression-oriented language, and variable bindings (which are expressions) are in scope until the end of the nearest enclosing { ... } block. The combination of these features means that some semantics must be given to a binding occurring inside of a short-circuited alternative.

<lang e>def x := a(i) && (def funky := b(j))</lang>

The choice we make is that funky is ordinary if the right-side expression was evaluated, and otherwise is ruined; attempts to access the variable give an error.

Forth

<lang forth>\ short-circuit conditional syntax, from Wil Baden

COND 0 ; immediate
THENS BEGIN dup WHILE postpone THEN REPEAT DROP ; immediate
ORIF s" ?DUP 0= IF" evaluate ; immediate
ANDIF s" DUP IF DROP" evaluate ; immediate
.bool IF ." true " ELSE ." false" THEN ;
A ." A=" dup .bool ;
B ." B=" dup .bool ;
test
 1 -1 DO 1 -1 DO
   CR I A drop space J B drop space
   ." : ANDIF " COND I A ANDIF drop J B    IF ."  (BOTH)"    THENS
   ." , ORIF "  COND I A  ORIF drop J B 0= IF ."  (NEITHER)" THENS
 LOOP LOOP ;

\ a more typical example

alnum? ( char -- ? )
 COND dup lower? ORIF dup upper? ORIF dup digit? THENS nip ;</lang>

Fortran

Works with: Fortran version 90 and later

Using an IF .. THEN .. ELSE construct <lang fortran>program Short_Circuit_Eval

 implicit none
 logical :: x, y
 logical, dimension(2) :: l = (/ .false., .true. /)
 integer :: i, j
 do i = 1, 2
   do j = 1, 2
     write(*, "(a,l1,a,l1,a)") "Calculating x = a(", l(i), ") and b(", l(j), ")"   
     ! a AND b
     x = a(l(i))  
     if(x) then
       x = b(l(j))
       write(*, "(a,l1)") "x = ", x
     else
       write(*, "(a,l1)") "x = ", x
     end if
 
     write(*,*)
     write(*, "(a,l1,a,l1,a)") "Calculating y = a(", l(i), ") or b(", l(j), ")"   
     ! a OR b
     y = a(l(i))
     if(y) then
       write(*, "(a,l1)") "y = ", y
     else
       y = b(l(j))
       write(*, "(a,l1)") "y = ", y
     end if
     write(*,*)
   end do
 end do

contains

function a(value)

 logical :: a
 logical, intent(in) :: value
 a = value
 write(*, "(a,l1,a)") "Called function a(", value, ")"

end function

function b(value)

 logical :: b
 logical, intent(in) :: value
 
 b = value
 write(*, "(a,l1,a)") "Called function b(", value, ")"

end function end program</lang> Output

Calculating x = a(F) and b(F)
Called function a(F)
x = F
 
Calculating y = a(F) or b(F)
Called function a(F)
Called function b(F)
y = F
 
Calculating x = a(F) and b(T)
Called function a(F)
x = F
 
Calculating y = a(F) or b(T)
Called function a(F)
Called function b(T)
y = T
 
Calculating x = a(T) and b(F)
Called function a(T)
Called function b(F)
x = F
 
Calculating y = a(T) or b(F)
Called function a(T)
y = T
 
Calculating x = a(T) and b(T)
Called function a(T)
Called function b(T)
x = T
 
Calculating y = a(T) or b(T)
Called function a(T)
y = T

Icon and Unicon

The entire concept of using 'boolean' values for logic control runs counter to the philosophy of Icon. Instead Icon has success (something that returns a result) and failure which is really a signal. The concept is similar to that used in SNOBOL4 and Lisp and far more potent than passing around and testing booleans. There is no way to pass around a 'false' value in that sense. Icon does have facilities for dealing with bits inside integers but these would not normally be used for control purposes. Because failure is a signal control is always evaluated in a short-circuit manner. One consequence of this is that an expression "i < j" doesn't return a boolean value, instead it returns the value of j. While this may seem odd at first it allows for elegant expressions like "i < j < k". Another benefit is that there is no need for programmers to devote effort to staying inside the bounds of any data type. For instance, if you loop and iterate beyond bounds the expression simply fails and the loop ends.

While this task could be written literally, it would be more beneficial to show how an Icon programmer would approach the same problem. Icon extends the idea short circuit evaluation with the ability for expressions to generate alternate results only if needed. For more information see Failure is an option, Everything Returns a Value Except when it Doesn't, and Goal-Directed Evaluation and Generators. Consequently some small liberties will be taken with this task:

  • Since any result means an expression succeeded and is hence true, we can use any value. In this example our choice will be determined by how we deal with 'false'.
  • The inability to pass a 'false' value is a challenge. At first glance we might try &null, similar to Lisp, but there is no canonical true. Also &null produces a result, so strictly speaking it could be 'true' as well. A good example of this is that an expression like " not expr " returns null if 'expr' fails.
  • For this example we will define two procedures 'true' and 'false'. Because Icon treats procedures as a data type we can assign them and invoke them indirectly via the variable name they are assigned to. We can write " i := true " and later invoke 'true' via " i() ".
  • Rather than have the tasks print their own name, we will just utilize built-in tracing which will be more informative.

This use of procedures as values is somewhat contrived but serves us well for demonstration purposes. In practice this approach would be strained since failure results aren't re-captured as values (and can't easily be).

Icon

<lang Icon>procedure main() &trace := -1 # ensures functions print their names

every (i := false | true ) & ( j := false | true) do {

 write("i,j := ",image(i),", ",image(j))
 write("i & j:")
 x := i() & j()   # invoke true/false
 write("i | j:")
 y := i() | j()   # invoke true/false
 }

end

procedure true() #: succeeds always (returning null) return end

procedure false() #: fails always fail # for clarity but not needed as running into end has the same effect end </lang>

Sample output for a single case:

i,j := procedure true, procedure false
i & j:
Shortcircuit.icn:    8  | true()
Shortcircuit.icn:   16  | true returned &null
Shortcircuit.icn:    8  | false()
Shortcircuit.icn:   20  | false failed
i | j:
Shortcircuit.icn:   10  | true()
Shortcircuit.icn:   16  | true returned &null
i,j := procedure true, procedure true

Unicon

The Icon solution works in Unicon.

J

See the J wiki entry on short circuit booleans.

<lang j>labeled=:1 :'[ smoutput@,&":~&m' A=: 'A ' labeled B=: 'B ' labeled and=: ^: or=: 2 :'u^:(-.@v)'</lang>

Example:

<lang> (A and B) 1 B 1 A 1 1

  (A and B) 0

B 0 0

  (A or B) 1

B 1 1

  (A or B) 0

B 0 A 0 0</lang>

Note that J evaluates right-to-left.

Note also that both functions take the same argument.

Java

In Java the boolean operators && and || are short circuit operators. The eager operator counterparts are & and |. <lang java>public class ShortCirc {

   public static void main(String[] args){
       System.out.println("F and F = " + (a(false) && b(false)) + "\n");
       System.out.println("F or F = " + (a(false) || b(false)) + "\n");
       System.out.println("F and T = " + (a(false) && b(true)) + "\n");
       System.out.println("F or T = " + (a(false) || b(true)) + "\n");
       System.out.println("T and F = " + (a(true) && b(false)) + "\n");
       System.out.println("T or F = " + (a(true) || b(false)) + "\n");
       System.out.println("T and T = " + (a(true) && b(true)) + "\n");
       System.out.println("T or T = " + (a(true) || b(true)) + "\n");
   }
   public static boolean a(boolean a){
       System.out.println("a");
       return a;
   }
   public static boolean b(boolean b){
       System.out.println("b");
       return b;
   }

}</lang> Output:

a
F and F = false

a
b
F or F = false

a
F and T = false

a
b
F or T = true

a
b
T and F = false

a
T or F = true

a
b
T and T = true

a
T or T = true

MUMPS

MUMPS evaluates every expression it encounters, so we have to use conditional statements to do a short circuiting of the expensive second task.

<lang MUMPS>SSEVAL1(IN)

WRITE !,?10,$STACK($STACK,"PLACE")
QUIT IN

SSEVAL2(IN)

WRITE !,?10,$STACK($STACK,"PLACE")
QUIT IN

SSEVAL3

NEW Z
WRITE "1 AND 1"
SET Z=$$SSEVAL1(1) SET:Z Z=Z&$$SSEVAL2(1)
WRITE !,$SELECT(Z:"TRUE",1:"FALSE")
WRITE !!,"0 AND 1"
SET Z=$$SSEVAL1(0) SET:Z Z=Z&$$SSEVAL2(1)
WRITE !,$SELECT(Z:"TRUE",1:"FALSE")
WRITE !!,"1 OR 1"
SET Z=$$SSEVAL1(1) SET:'Z Z=Z!$$SSEVAL2(1)
WRITE !,$SELECT(Z:"TRUE",1:"FALSE")
WRITE !!,"0 OR 1"
SET Z=$$SSEVAL1(0) SET:'Z Z=Z!$$SSEVAL2(1)
WRITE !,$SELECT(Z:"TRUE",1:"FALSE")
KILL Z
QUIT</lang>

Output:

USER>D SSEVAL3^ROSETTA
1 AND 1
          SSEVAL1+1^ROSETTA +3
          SSEVAL2+1^ROSETTA +3
TRUE
 
0 AND 1
          SSEVAL1+1^ROSETTA +3
FALSE
 
1 OR 1
          SSEVAL1+1^ROSETTA +3
TRUE
 
0 OR 1
          SSEVAL1+1^ROSETTA +3
          SSEVAL2+1^ROSETTA +3
TRUE

OCaml

<lang ocaml> let a r = print_endline " > function a called"; r let b r = print_endline " > function b called"; r

let test_and b1 b2 =

 Printf.printf "# testing (%b && %b)\n" b1 b2;
 ignore (a b1 && b b2)

let test_or b1 b2 =

 Printf.printf "# testing (%b || %b)\n" b1 b2;
 ignore (a b1 || b b2)

let test_this test =

 test true true;
 test true false;
 test false true;
 test false false;

let () =

 print_endline "==== Testing and ====";
 test_this test_and;
 print_endline "==== Testing or ====";
 test_this test_or;
</lang>

output:

==== Testing and ====
# testing (true && true)
 > function a called
 > function b called
# testing (true && false)
 > function a called
 > function b called
# testing (false && true)
 > function a called
# testing (false && false)
 > function a called
==== Testing or ====
# testing (true || true)
 > function a called
# testing (true || false)
 > function a called
# testing (false || true)
 > function a called
 > function b called
# testing (false || false)
 > function a called
 > function b called

The AND and OR predicates may take either expressions which are all evaluated beforehand, or lists which are short-circuit evaluated from left to right only until the overall value of the expression can be determined. <lang logo> and [notequal? :x 0] [1/:x > 3] (or [:x < 0] [:y < 0] [sqrt :x + sqrt :y < 3]) </lang>

Lua

<lang lua>function a(i)

   print "Function a(i) called."
   return i

end

function b(i)

   print "Function b(i) called."
   return i

end

i = true x = a(i) and b(i); print "" y = a(i) or b(i); print ""

i = false x = a(i) and b(i); print "" y = a(i) or b(i)</lang>

Oz

Oz' andthen and orelse operators are short-circuiting, as indicated by their name. The library functions Bool.and and Bool.or are not short-circuiting, on the other hand.

<lang oz>declare

 fun {A Answer}
    AnswerS = {Value.toVirtualString Answer 1 1}
 in
    {System.showInfo "  % Called function {A "#AnswerS#"} -> "#AnswerS}
    Answer
 end
 fun {B Answer}
    AnswerS = {Value.toVirtualString Answer 1 1}
 in
    {System.showInfo "  % Called function {B "#AnswerS#"} -> "#AnswerS}
    Answer
 end

in

 for I in [false true] do
    for J in [false true] do
       X Y
    in
       {System.showInfo "\nCalculating: X = {A I} andthen {B J}"}
       X = {A I} andthen {B J}
       {System.showInfo "Calculating: Y = {A I} orelse {B J}"}
       Y = {A I} orelse {B J}
    end
 end</lang>

Output: <lang oz>Calculating: X = {A I} andthen {B J}

 % Called function {A false} -> false

Calculating: Y = {A I} orelse {B J}

 % Called function {A false} -> false
 % Called function {B false} -> false

Calculating: X = {A I} andthen {B J}

 % Called function {A false} -> false

Calculating: Y = {A I} orelse {B J}

 % Called function {A false} -> false
 % Called function {B true} -> true

Calculating: X = {A I} andthen {B J}

 % Called function {A true} -> true
 % Called function {B false} -> false

Calculating: Y = {A I} orelse {B J}

 % Called function {A true} -> true

Calculating: X = {A I} andthen {B J}

 % Called function {A true} -> true
 % Called function {B true} -> true

Calculating: Y = {A I} orelse {B J}

 % Called function {A true} -> true</lang>

PARI/GP

<lang>a(n)={

 print(a"("n")");
 a

}; b(n)={

 print("b("n")");
 n

}; or(A,B)={

 a(A) || b(B)

}; and(A,B)={

 a(A) && b(B)

};</lang>

Pascal

Standard Pascal

Standard Pascal doesn't have native short-circuit evaluation. <lang pascal> program shortcircuit(output);

function a(value: boolean): boolean;

begin
 writeln('a(', value, ')');
 a := value
end;

function b(value:boolean): boolean;

begin
 writeln('b(', value, ')');
 b := value
end;

procedure scandor(value1, value2: boolean);

var
 result: integer;
begin
 {and}
 if a(value1)
  then
   result := b(value2)
  else
   result := false;
 writeln(value1, ' and ', value2, ' = ', result);
 {or}
 if a(value1)
  then
   result := true
  else
   result := b(value2)
 writeln(value1, ' or ', value2, ' = ', result)
end;

begin

scandor(false, false);
scandor(false, true);
scandor(true, false);
scandor(true, true);

end. </lang>

Turbo Pascal

Turbo Pascal allows short circuit evaluation with a compiler switch: <lang pascal> program shortcircuit;

function a(value: boolean): boolean;

begin
 writeln('a(', value, ')');
 a := value
end;

function b(value:boolean): boolean;

begin
 writeln('b(', value, ')');
 b := value
end;

{$B-} {enable short circuit evaluation} procedure scandor(value1, value2: boolean);

var
 result: integer;
begin
 result :=  a(value1) and b(value)
 writeln(value1, ' and ', value2, ' = ', result);
 result := a(value1) or b(value2);
 writeln(value1, ' or ', value2, ' = ', result)
end;

begin

scandor(false, false);
scandor(false, true);
scandor(true, false);
scandor(true, true);

end. </lang>

Extended Pascal

The extended Pascal standard introduces the operators and_then and or_else for short-circuit evaluation. <lang pascal> program shortcircuit(output);

function a(value: boolean): boolean;

begin
 writeln('a(', value, ')');
 a := value
end;

function b(value:boolean): boolean;

begin
 writeln('b(', value, ')');
 b := value
end;

procedure scandor(value1, value2: boolean);

var
 result: integer;
begin
 result :=  a(value1) and_then b(value)
 writeln(value1, ' and ', value2, ' = ', result);
 result := a(value1) or_else b(value2);
 writeln(value1, ' or ', value2, ' = ', result)
end;

begin

scandor(false, false);
scandor(false, true);
scandor(true, false);
scandor(true, true);

end. </lang>

Note: GNU Pascal allows and then and or else as alternatives to and_then and or_else.

Perl

Perl uses short-circuit boolean evaluation.

<lang Perl>sub a { print 'A'; return $_[0] } sub b { print 'B'; return $_[0] }

  1. Test-driver

sub test {

   for my $op ('&&','||') {
       for (qw(1,1 1,0 0,1 0,0)) {
          my ($x,$y) = /(.),(.)/;
          print my $str = "a($x) $op b($y)", ': ';
          eval $str; print "\n"; } }

}

  1. Test and display

test();</lang>

Output:

a(1) && b(1): AB
a(1) && b(0): AB
a(0) && b(1): A
a(0) && b(0): A
a(1) || b(1): A
a(1) || b(0): A
a(0) || b(1): AB
a(0) || b(0): AB

Perl 6

<lang Perl6>sub a ($p) { print 'a'; $p } sub b ($p) { print 'b'; $p }

for '&&', '||' -> $op {

   for True, False X True, False -> $p, $q {
       my $s = "a($p) $op b($q)";
       print "$s: ";
       eval $s;
       print "\n";
   }

}</lang>

Output:

a(1) && b(1): ab
a(1) && b(0): ab
a(0) && b(1): a
a(0) && b(0): a
a(1) || b(1): a
a(1) || b(0): a
a(0) || b(1): ab
a(0) || b(0): ab

PicoLisp

<lang PicoLisp>(de a (F)

  (msg 'a)
  F )

(de b (F)

  (msg 'b)
  F )

(mapc

  '((I J)
     (for Op '(and or)
        (println I Op J '-> (Op (a I) (b J))) ) )
  '(NIL NIL T T)
  '(NIL T NIL T) )</lang>

Output:

a
NIL and NIL -> NIL
a
b
NIL or NIL -> NIL
a
NIL and T -> NIL
a
b
NIL or T -> T
a
b
T and NIL -> NIL
a
T or NIL -> T
a
b
T and T -> T
a
T or T -> T

Prolog

Prolog has not functions but predicats succeed of fail.
Tested with SWI-Prolog. Should work with other dialects. <lang Prolog>short_circuit :- ( a_or_b(true, true) -> writeln('==> true'); writeln('==> false')) , nl, ( a_or_b(true, false)-> writeln('==> true'); writeln('==> false')) , nl, ( a_or_b(false, true)-> writeln('==> true'); writeln('==> false')) , nl, ( a_or_b(false, false)-> writeln('==> true'); writeln('==> false')) , nl, ( a_and_b(true, true)-> writeln('==> true'); writeln('==> false')) , nl, ( a_and_b(true, false)-> writeln('==> true'); writeln('==> false')) , nl, ( a_and_b(false, true)-> writeln('==> true'); writeln('==> false')) , nl, ( a_and_b(false, false)-> writeln('==> true'); writeln('==> false')) .


a_and_b(X, Y) :- format('a(~w) and b(~w)~n', [X, Y]), ( a(X), b(Y)).

a_or_b(X, Y) :- format('a(~w) or b(~w)~n', [X, Y]), ( a(X); b(Y)).

a(X) :- format('a(~w)~n', [X]), X.

b(X) :- format('b(~w)~n', [X]), X. </lang> Output <lang Prolog>?- short_circuit. a(true) or b(true) a(true) ==> true

a(true) or b(false) a(true) ==> true

a(false) or b(true) a(false) b(true) ==> true

a(false) or b(false) a(false) b(false) ==> false

a(true) and b(true) a(true) b(true) ==> true

a(true) and b(false) a(true) b(false) ==> false

a(false) and b(true) a(false) ==> false

a(false) and b(false) a(false) ==> false

true. </lang>

PureBasic

Logical And & Or operators will not evaluate their right-hand expression if the outcome can be determined from the value of the left-hand expression. <lang PureBasic>Procedure a(arg)

 PrintN("  # Called function a("+Str(arg)+")")  
 ProcedureReturn arg

EndProcedure

Procedure b(arg)

 PrintN("  # Called function b("+Str(arg)+")")
 ProcedureReturn arg

EndProcedure

OpenConsole() For a=#False To #True

 For b=#False To #True
   PrintN(#CRLF$+"Calculating: x = a("+Str(a)+") And b("+Str(b)+")")
   x= a(a) And b(b)
   PrintN("Calculating: x = a("+Str(a)+") Or b("+Str(b)+")")
   y= a(a) Or b(b) 
 Next

Next Input()</lang>

Calculating: x = a(0) And b(0)
  # Called function a(0)
Calculating: x = a(0) Or b(0)
  # Called function a(0)
  # Called function b(0)

Calculating: x = a(0) And b(1)
  # Called function a(0)
Calculating: x = a(0) Or b(1)
  # Called function a(0)
  # Called function b(1)

Calculating: x = a(1) And b(0)
  # Called function a(1)
  # Called function b(0)
Calculating: x = a(1) Or b(0)
  # Called function a(1)

Calculating: x = a(1) And b(1)
  # Called function a(1)
  # Called function b(1)
Calculating: x = a(1) Or b(1)
  # Called function a(1)

Python

Pythons and and or binary, infix, boolean operators will not evaluate their right-hand expression if the outcome can be determined from the value of the left-hand expression. <lang python>>>> def a(answer): print(" # Called function a(%r) -> %r" % (answer, answer)) return answer

>>> def b(answer): print(" # Called function b(%r) -> %r" % (answer, answer)) return answer

>>> for i in (False, True): for j in (False, True): print ("\nCalculating: x = a(i) and b(j)") x = a(i) and b(j) print ("Calculating: y = a(i) or b(j)") y = a(i) or b(j)


Calculating: x = a(i) and b(j)

 # Called function a(False) -> False

Calculating: y = a(i) or b(j)

 # Called function a(False) -> False
 # Called function b(False) -> False

Calculating: x = a(i) and b(j)

 # Called function a(False) -> False

Calculating: y = a(i) or b(j)

 # Called function a(False) -> False
 # Called function b(True) -> True

Calculating: x = a(i) and b(j)

 # Called function a(True) -> True
 # Called function b(False) -> False

Calculating: y = a(i) or b(j)

 # Called function a(True) -> True

Calculating: x = a(i) and b(j)

 # Called function a(True) -> True
 # Called function b(True) -> True

Calculating: y = a(i) or b(j)

 # Called function a(True) -> True</lang>

Pythons if expression can also be used to the same ends (but probably should not): <lang python>>>> for i in (False, True): for j in (False, True): print ("\nCalculating: x = a(i) and b(j) using x = b(j) if a(i) else False") x = b(j) if a(i) else False print ("Calculating: y = a(i) or b(j) using y = b(j) if not a(i) else True") y = b(j) if not a(i) else True


Calculating: x = a(i) and b(j) using x = b(j) if a(i) else False

 # Called function a(False) -> False

Calculating: y = a(i) or b(j) using y = b(j) if not a(i) else True

 # Called function a(False) -> False
 # Called function b(False) -> False

Calculating: x = a(i) and b(j) using x = b(j) if a(i) else False

 # Called function a(False) -> False

Calculating: y = a(i) or b(j) using y = b(j) if not a(i) else True

 # Called function a(False) -> False
 # Called function b(True) -> True

Calculating: x = a(i) and b(j) using x = b(j) if a(i) else False

 # Called function a(True) -> True
 # Called function b(False) -> False

Calculating: y = a(i) or b(j) using y = b(j) if not a(i) else True

 # Called function a(True) -> True

Calculating: x = a(i) and b(j) using x = b(j) if a(i) else False

 # Called function a(True) -> True
 # Called function b(True) -> True

Calculating: y = a(i) or b(j) using y = b(j) if not a(i) else True

 # Called function a(True) -> True</lang>

REXX

REXX doesn;t have native short circuits. <lang>

 do i=-2 to 2
 x=a(i) & b(i)
 y=a(i)
 if \y then y=b(i)
 say copies('-',30) 'x='||x 'y='y 'i='i
 end

exit

a: say 'A entered with:' arg(1);return abs(arg(1)//2) /*1=odd, 0=even */ b: say 'B entered with:' arg(1);return arg(1)<0 /*1=neg, 0=if not*/ </lang> Output:

B entered with: -2
A entered with: -2
A entered with: -2
B entered with: -2
------------------------------ x=0 y=1 i=-2
B entered with: -1
A entered with: -1
A entered with: -1
------------------------------ x=1 y=1 i=-1
B entered with: 0
A entered with: 0
A entered with: 0
B entered with: 0
------------------------------ x=0 y=0 i=0
B entered with: 1
A entered with: 1
A entered with: 1
------------------------------ x=0 y=1 i=1
B entered with: 2
A entered with: 2
A entered with: 2
B entered with: 2
------------------------------ x=0 y=0 i=2

Ruby

Binary operators are short-circuiting. Demonstration code: <lang ruby>def a( bool )

 puts "a( #{bool} ) called"
 bool

end

def b( bool )

 puts "b( #{bool} ) called"
 bool

end

[true, false].each do |a_val|
  [true, false].each do |b_val|
    puts "a( #{a_val} ) and b( #{b_val} ) is #{a( a_val ) and b( b_val )}."
    puts
    puts "a( #{a_val} ) or b( #{b_val} ) is #{a( a_val)  or b( b_val )}."
    puts
  end
end

</lang> Output:


a( true ) called
b( true ) called
a( true ) and b( true ) is true.

a( true ) called
a( true ) or b( true ) is true.

a( true ) called
b( false ) called
a( true ) and b( false ) is false.

a( true ) called
a( true ) or b( false ) is true.

a( false ) called
a( false ) and b( true ) is false.

a( false ) called
b( true ) called
a( false ) or b( true ) is true.

a( false ) called
a( false ) and b( false ) is false.

a( false ) called
b( false ) called
a( false ) or b( false ) is false.

Scheme

<lang scheme>>(define (a x)

  (display "a\n")
  x)

>(define (b x)

  (display "b\n")
  x)

>(for-each (lambda (i)

  (for-each (lambda (j)
    (display i) (display " and ") (display j) (newline)
    (and (a i) (b j))
    (display i) (display " or ") (display j) (newline)
    (or (a i) (b j))
   ) '(#t #f))
 ) '(#t #f))
  1. t and #t

a b

  1. t or #t

a

  1. t and #f

a b

  1. t or #f

a

  1. f and #t

a

  1. f or #t

a b

  1. f and #f

a

  1. f or #f

a b </lang>

SNOBOL4

Because of its unique success/failure model of flow control, Snobol does not use standard boolean operators or assignment. However, in &fullscan mode Snobol exhibits short-circuit boolean behavior in pattern matches, with concatenation " " functioning as logical AND, and alternation " | " as logical OR.

The test statements below use a pattern constructed from the functions a( ) and b( ) and match it to the null string with deferred evaluation. This idiom allows the functions to self-report the expected short-circuit patterns.

<lang SNOBOL4> define('a(val)') :(a_end) a out = 'A '

       eq(val,1) :s(return)f(freturn)

a_end

       define('b(val)') :(b_end)

b out = 'B '

       eq(val,1) :s(return)f(freturn)

b_end

  • # Test and display
       &fullscan = 1
       output(.out,1,'-[-r1]') ;* Macro Spitbol
  • output(.out,1,'B','-')  ;* CSnobol
       define('nl()'):(nlx);nl output = :(return);nlx

       out = 'T and T: '; null ? *a(1) *b(1); nl()
       out = 'T and F: '; null ? *a(1) *b(0); nl() 
       out = 'F and T: '; null ? *a(0) *b(1); nl() 
       out = 'F and F: '; null ? *a(0) *b(0); nl() 
       output = 
       out = 'T or T: '; null ? *a(1) | *b(1); nl() 
       out = 'T or F: '; null ? *a(1) | *b(0); nl() 
       out = 'F or T: '; null ? *a(0) | *b(1); nl() 
       out = 'F or F: '; null ? *a(0) | *b(0); nl() 

end</lang>

Output:

T and T: A B
T and F: A B
F and T: A
F and F: A

T or T: A
T or F: A
F or T: A B
F or F: A B

Tcl

The && and || in the expr command support short-circuit evaluation. It is recommended that you always put expressions in braces so that and command or variable substitutions are applied at the right time rather than before the expression is evaluated at all. (Indeed, it is recommended that you do that anyway as unbraced expressions cannot be efficiently compiled.) <lang tcl>package require Tcl 8.5 proc tcl::mathfunc::a boolean {

   puts "a($boolean) called"
   return $boolean

} proc tcl::mathfunc::b boolean {

   puts "b($boolean) called"
   return $boolean

}

foreach i {false true} {

   foreach j {false true} {
       set x [expr {a($i) && b($j)}]
       puts "x = a($i) && b($j) = $x"
       set y [expr {a($i) || b($j)}]
       puts "y = a($i) || b($j) = $y"
       puts ""; # Blank line for clarity
   }

}</lang> Output (note that booleans may be written out words or numeric):

a(false) called
x = a(false) && b(false) = 0
a(false) called
b(false) called
y = a(false) || b(false) = 0

a(false) called
x = a(false) && b(true) = 0
a(false) called
b(true) called
y = a(false) || b(true) = 1

a(true) called
b(false) called
x = a(true) && b(false) = 0
a(true) called
y = a(true) || b(false) = 1

a(true) called
b(true) called
x = a(true) && b(true) = 1
a(true) called
y = a(true) || b(true) = 1