Module /fusion/bool
Boolean operations and related conditional forms.
Conditionals
Fusion's if form is an expression not a statement, so it's closer to
the "ternary operator" (?:) of C-like languages than to their
if/then/else statement:
(if true "yes" "no") ==> "yes"
(if false "yes" "no") ==> "no"
An if expression takes three sub-expressions, the test
expression, the "then-expression", and the "else-expression". Only one of the
latter two is evaluated, and both are required. Because of that evaluation
rule, if is a syntactic form, not a procedure; otherwise both branches would
be evaluated, which would defeat the purpose.
When you don't want to supply both result clauses, you can use when
or unless:
(when (is_null some_value)
(displayln "The value is null."))
(unless (is_null some_value)
(displayln "The value is not null."))
Both examples either display a line of text or do nothing.
Truthiness
Fusion's conditional expressions branch based on the "truthiness" of the
condition value, which means the result of the condition expression
doesn't need to be strictly true or false. It can be any kind of value,
which is then treated as either "truthy" or "untruthy" for the purposes of the
condition.
To see the difference between "truth" and "truthy", consider these expressions:
(if 0 "yes" "no")
(if "" "yes" "no")
(if null "yes" "no")
(if (void) "yes" "no")
This sort of thing is a common idiom in dynamic languages, a shortcut
to checking the presence of a meaningful value. In Java the program must have
an explicit comparison to achieve a true/false value. Fusion has the added
hiccup of null.bool. Early versions of Fusion forced the programmer to ensure
that the value is exactly true or false, but that caused an abundance of
null checks and void checks for very common use cases. (Users of the IonJava
APIs will surely recognize this problem!) Scheme languages don't have null,
and they generally say that everything is truthy except for false. That's
more forgiving, but not necessarily more convenient, especially when you throw
in all those nulls.
Fusion defines truthiness as follows:
- Every value is truthy except for
false, void, and any variant ofnull.
Given historical experience in working with Ion data, we believe this will be the most convenient approach to the issue. This definition is more lax (and hopefully more convenient) than Java, but less lenient (and hopefully less error-prone) than C or C++.
Fusion supports the usual boolean combinators and, or, and
not, which also observe truthiness in the same manner. The operators
and and or are syntactic forms (not procedures) that perform
short-circuiting a la Java's && and || operators. Unlike Java, these
forms return the result of the last expression evaluated rather than always
true or false.
(and true false) ==> false
(and 2 "truthy") ==> "truthy"
(and 2 "truthy" null false) ==> null
(or false true false) ==> true
(or false null.blob 0 1) ==> 0
Exported Bindings
(and expr ...)
Evaluates the exprs from left to right, returning the first untruthy value
that results (and ignoring further expressions). If they all return truthy
values, the last one is returned.
The last expr is in tail position. Given no exprs, the result is true.
(cond (test body ...) ...)
Evaluates the test expressions left to right until one returns a truthy value,
then evaluates the corresponding body expressions in tail position.
If no test is truthy, the result is void.
(if test then else)
Evaluates the test expression first. If the result is truthy, evaluates the
then expression and returns its value. Otherwise, evaluates the else
expression and returns its value.
All values are "truthy" except for false, void, and any variant of null.
Note that only one of then or else expressions is evaluated, and both are
in tail position.
(is_bool value)
Determines whether a value is of type bool, returning true or false.
(is_false v)
Returns true when the argument is false (annotated or not), or false
otherwise.
Equivalent to:
(== v false)
(is_true v)
Returns true when the argument is true (annotated or not), or false
otherwise.
Equivalent to:
(== v true)
(is_truthy v)
Returns true when the argument is truthy, or false otherwise.
Fusion defines truthiness as follows:
- Every value is truthy except for
false, void, and any variant ofnull.
Equivalent to:
(if v true false)
See also: Truthiness
(is_untruthy v)
Returns true when the argument is not truthy, or false otherwise.
The untruthy values are false, void, and any variant of null.
Equivalent to:
(if v false true)
See also: Truthiness
(not value)
Returns true if value is untruthy, false if value is truthy. Truthiness
is as defined by if.
(or expr ...)
Evaluates the exprs from left to right, returning the first truthy value
that results (and ignoring further expressions). If they all return untruthy
values, the last one is returned.
The last expr is in tail position. Given no exprs, the result is false.
(unless test body ...)
Evaluates the test, and if it is not truthy, evaluates the body forms
left to right. The last body is in tail position, and its result is the
result of the entire form. If the body isn't evaluated, the result is void.
A companion form is when.
(when test body ...)
Evaluates the test, and if it is truthy, evaluates the body forms left
to right. The last body is in tail position, and its result is the result of
the entire form. If the body isn't evaluated, the result is void.
A companion form is unless.