Conditional Expression
Expr := "if" Expr "then" Expr "else" Expr "end"
The condition must be a formula, that is, an expression of arity 0.
If the condition is true
, then the value of the expression is the value of the expression in the then
branch, and the expression in the else
branch is not evaluated.
Otherwise the value is the value of the expression in the else
branch, and the expression in the then
branch is not evaluated.
The then
and else
branches can have arbitrary arity.
The expression if e1 then e2 else e3 end
has the same meaning as (e1, e2); (not(e1), e3)
.
Examples:
if 1 < 2 then 'a' else 'b' end
This gives ('a',)
.
def p = 1
def q = 2,3
def r = 4,5
def output = if p(1) then q else r end
This gives (2, 3)
.
def output = if p > 1 then q else r end
This gives (4, 5)
.
def p = 1; 2; 3
def output = if x = 1 then 'a' else 'b' end for x in p
This gives the following:
(1, 'a')
(2, 'b')
(3, 'b')
Conditional expressions can be nested, as shown in the example below, which defines a relation that computes the factorial of a positive integer.
The relation is named my_factorial
to avoid conflict with the function factorial
in the Standard Library.
See also the annotation @ondemand
.
// read query
@ondemand
def my_factorial[n in Int] =
if n < 0 then false
else if n = 0 then 1
else n * my_factorial[n - 1]
end
end
def output = my_factorial[5]
In Rel such definitions are usually expressed in a more idiomatic way:
@ondemand
def my_factorial[n in Int] = 1, n = 0
def my_factorial[n in Int] = n * my_factorial[n - 1], n > 0
This version features the infix comma operator, which denotes the Cartesian
product of its arguments.
If n = 0
is true
, then the body of the first definition will be 1
, which is the Cartesian product of {(1,)}
and {()}
.
In that case the body of the second definition will be the empty relation,
because n > 0
will be false
, that is {}
, and a Cartesian product of
anything with an empty relation is an empty relation.
Similarly, if n > 0
, then the body of the first definition will be the empty relation, and the body of the second definition will be the relation produced by the expression that precedes the comma.
You can think of n = 0
and n > 0
as guards that allow each of the two definitions to be used only in some particular situations.
If these guards are mutually exclusive, then the effect is a more concise formulation of what can be achieved with a conditional expression or nested conditional expressions.
Note that, in general, these guards do not have to be mutually exclusive.
If they are not, then both definitions will contribute to the result for a given value of n
, and the effect may be different from that of a conditional expression.
In this particular example, however, changing n > 0
to n >= 0
will not affect the result, because my_factorial[-1]
will produce an empty relation.
Next: Constants