Short-circuit evaluation: Difference between revisions

Content added Content deleted
(→‎{{header|Icon}}: better example)
Line 118: Line 118:
</pre>
</pre>
== Icon and Unicon ==
== 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 [[:Category:SNOBOL4|SNOBOL4]] and [[:Category:Lisp|Lisp]]. There is no way to pass around a 'false' value in that sense. 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".
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 [[:Category:SNOBOL4|SNOBOL4]] and [[:Category:Lisp|Lisp]] and far more potent than passing around and testing booleans. There is no way to pass around a 'false' value in that sense. 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".


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 [[Icon%2BUnicon/Intro#Program_Flow_and_Control|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:
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 [[Icon%2BUnicon/Intro#Program_Flow_and_Control|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'.
* 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).
* 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.
* 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' this via " i() ".
* Rather than have the tasks print their own name, we will just utilize built-in tracing which will be more informative.
* 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.
==={{header|Icon}}===
==={{header|Icon}}===
<lang Icon>procedure main()
<lang Icon>procedure main()
Line 139: Line 141:
end
end


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


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