Short-circuit evaluation: Difference between revisions
(added scheme) |
(→{{header|Oz}}: Added impl.) |
||
Line 109: | Line 109: | ||
a |
a |
||
T or T = true</pre> |
T or T = true</pre> |
||
=={{header|Oz}}== |
|||
Oz' <code>andthen</code> and <code>orelse</code> operators are short-circuiting, as indicated by their name. The library functions <code>Bool.and</code> and <code>Bool.or</code> 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 "\nCalculating: 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> |
|||
=={{header|PureBasic}}== |
=={{header|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. |
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. |
Revision as of 19:47, 24 July 2010
Assume functions a and b return boolean values, and further, the execution of function b takes considerable resources 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(j) or b(j)
If the language does not have short-circuit evaluation, this might be achieved with nested if statements.
Icon and Unicon
The entire concept of using 'boolean' values for logic control runs counter to the philosophy of Icon. While this task could be written literally, it would be more beneficial to show how an Icon programmer would approach the same problem. Icon already embraces the idea of short circuit evaluation and goes further with the ability of 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:
- For false we will use the null value &null and true we will use anything else (a 1 will do).
- Short-circuit evaluation uses success (a result) and failure (a signal that cannot be ignored and no result) so strictly speaking the boolean false will not be returned (only the failure signal).
- Rather than have the tasks print their own name, we will just utilize built-in tracing which will be more informative.
Icon
<lang Icon>procedure main() &trace := -1 # ensures a and b print their names
every (i := &null | 1 ) & ( j := &null | 1) do {
write("i,j := ",image(i),", ",image(j)) write("a & b:") x := a(i) & b(j) write("a | b:") y := a(i) | b(j) }
end
procedure a(x) #: returns x if x is non-null or fails otherwise return \x end
procedure b(x) return \x end</lang>
Sample output for a single case:
i,j := &null, 1 a & b: shortcicuit.icn: 10 | a(&null) shortcicuit.icn: 19 | a failed a | b: shortcicuit.icn: 12 | a(&null) shortcicuit.icn: 19 | a failed shortcicuit.icn: 12 | b(1) shortcicuit.icn: 23 | b returned 1
Unicon
The Icon solution works in Unicon.
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
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 "\nCalculating: 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>
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>
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))
- t and #t
a b
- t or #t
a
- t and #f
a b
- t or #f
a
- f and #t
a
- f or #t
a b
- f and #f
a
- f or #f
a b </lang>