This tutorial introduces functionality for conditionally selecting the value of a node.
The special case
operator selects the value of the first node for
which the value of the corresponding condition node is true. The
case
operator is special in that it has a special syntax to make it
more readable.
The |
Syntax.
case( condition-1 : value-1, condition-2 : value-2, .... default-value )
Each argument is of the form condition : value
where condition
is
the condition node and value
is the corresponding value node. The
last argument may also be of the form value
, that is there is no
condition node, in which case it becomes the default or else value.
The case
functor node evaluates to the value of the value node
corresponding to the first condition node which has a true value
(equal to the value of the builtin node True
), or the value of the
default node, if any, when all condition nodes have a false (equal
to the value of the builtin node False
) value.
Example.
case( a > b : a - b b > a : b - a 0 )
If the node a > b
evaluates to true, the case
node evaluates to
the value of a - b
, otherwise if b > a
evaluates to true, the
case
node evaluates to the value of b - a
. If neither a > b
nor
b > a
evaluate to true, the case
node evaluates to 0
.
If the default value node is omitted and no condition node evaluates
to true, the case
node evaluates to a failure value (you will learn
about failure values in a later tutorial which introduces error
handling).
Let’s write a simple case
expression which returns the maximum of
two numbers, a
and b
, and returns the string “neither” when
neither number is greater than the other.
The case
expression should evaluate to:
a
if a > b
b
if b > a
These conditions are implemented by the following case
expression:
case( a > b : a, b > a : b, "neither" )
String constants are written in double quotes |
Notice that the last argument does not have an associated
condition. The case
node evaluates to this argument if none of the
conditions, of the previous arguments, evaluate to true.
We can incorporate this in a simple application, which displays the maximum of two numbers entered by the user, using the following HTML interface:
ui.html
.
<? /import(core) maximum <- case ( a > b : a, b > a : b, "neither" ) ?> <!doctype html> <html> <head> <title>Maximum</title> </head> <body> <h1>Maximum</h1> <div><label>A: <input value="<?@ to-int(a) ?>"/></label></div> <div><label>B: <input value="<?@ to-int(b) ?>"/></label></div> <hr/> <div><strong>The maximum of <?@ a ?> and <?@ b ?> is <?@ maximum ?>.</strong></div> </body> </html>
The |
The interface consists of two text fields, the contents of which are
bound to nodes a
and b
. The to-int
operator is used to convert
the string values to integers as in the previous tutorial.
The node maximum
is bound to the value of the case
functor, and
its value is displayed in an unnamed HTML element below the input
fields.
The values of |
Build and run the application, using the same build configuration file and command from the previous tutorials.
Enter some numbers in the text fields:
Notice that the maximum, 15 in this case, is displayed below the text fields. Also notice that the values entered in the text fields are displayed as part of the message.
Now change the number, which is the maximum, to a different value which is still greater than the other number:
The new maximum is displayed. This demonstrates that if the values of
the value nodes, of the case
expression change, the value of the
case
expression is updated.
Change the maximum number such that it is smaller than the other number:
This shows that the value of the case
expression is also updated if
the values of the condition nodes change.
Now finally change the numbers such that they are both equal:
The displayed maximum is “neither” which is the default value of the case expression.
Let’s extend the application developed during the previous tutorial by adding the functionality for specifying a limit to the sum of the two numbers. The application should inform the user of whether the limit was exceeded.
Start with the following slightly modified code from the previous tutorial.
<? /import(core) a + b -> sum ?> <!doctype html> <html> <head> <title>Sum Limit</title> </head> <body> <h1>Sum Limit</h1> <div><label>Limit: <input value="<?@ to-int(limit) ?>"/></label></div> <hr/> <div><label>A: <input value="<?@ to-int(a) ?>"/></label></div> <div><label>B: <input value="<?@ to-int(b) ?>"/></label></div> <hr/> <div><strong>A + B = <?@ sum ?></strong></div> </body> </html>
A new text input field for the limit has been added, with its value
bound to the node limit
.
The sum |
The message “Within limit.” should be displayed if the sum is less
than the limit (sum < limit
), and “Limit Exceeded!”
otherwise. This can be implemented using the following case
expression, which is bound directly to an unnamed element.
Add the following below the element where the sum is displayed.
<div> <?@ case( sum < limit : "Within Limit.", "Limit Exceeded!" ) ?> </div>
There is no difference in efficiency between using the |
Build and run the application, and enter some initial values for the
limit, a
and b
.
“Limit Exceeded!” is displayed since the sum of 11 did indeed exceed the limit of 10, with the numbers in the snapshot above.
Now try increasing the limit:
The message changes to “Within Limit.”.
Whilst the application we’ve implemented so far demonstrates the power of functional bindings, it is rather lacking in that whether the limit has been exceeded or not is only indicated by text. The text has to be read in full to determine whether the limit was exceeded, and changes from Within Limit to Limit Exceeded, and vice versa, are hard to notice. Some visual indications, such as a change in the color of the sum, when the limit is exceeded, would be helpful.
As an improvement, we would like the text color of the the sum, and the status message, to be red when the sum exceeds the limit, and to be green when it is within the limit.
Let’s start off by giving an ID to the elements in which the sum and
status message are displayed, so that they can be referenced from
Tridash code. Surround <?@ sum ?>
in a span
element with ID sum
and assign the div
element, containing the status message, the ID
status
.
<div><strong>A + B = <span id="sum"><?@ sum ?></span></strong></div> <div id="status"> <?@ case( sum < limit : "Within Limit.", "Limit Exceeded!" ) ?> </div>
Let’s create a node color
which will be bound to the text color in
which the sum and status message should be displayed. It should have
the value "green"
when the sum is within the limit and the value
"red"
when the sum exceeds the limit. This can be achieved by
binding to a case
functor node.
The values |
Add the following to the Tridash code tag.
case( sum < limit : "green", "red" ) -> color
The value of the case
functor node is "green"
if sum
is less
than limit
and "red"
otherwise. The case functor node is bound to
the color
node.
The color
node somehow has to be bound to the text color of the
sum
and status
elements. Text color is a style attribute of an
element. All style attributes are grouped under a single subnode
style
of the HTML element node. The text color is controlled by the
color
attribute, referenced using style.color
.
The color
node is bound to the style attributes of the elements with
the following (add to the Tridash code tag):
color -> self.sum.style.color color -> self.status.style.color
Full ui.html
code:
ui.html.
<? /import(core) a + b -> sum case ( sum < limit : "green", "red" ) -> color color -> self.sum.style.color color -> self.status.style.color ?> <!doctype html> <html> <head> <title>Sum Limit</title> </head> <body> <h1>Sum Limit</h1> <div><label>Limit: <input value="<?@ to-int(limit) ?>"/></label></div> <hr/> <div><label>A: <input value="<?@ to-int(a) ?>"/></label></div> <div><label>B: <input value="<?@ to-int(b) ?>"/></label></div> <hr/> <div><strong>A + B = <span id="sum"><?@ sum ?></span></strong></div> <div id="status"> <?@ case( sum < limit : "Within Limit.", "Limit Exceeded!" ) ?> </div> </body> </html>
Build and run the application. Enter some values for a
, b
and the
limit such that the sum exceeds the limit.
The status message and sum are now shown in red which provides an immediate visual indication that the limit has been exceeded.
Now increase the limit, or decrease the values of a
and b
:
The color of the status message and sum is immediately changed to green, which provides a noticeable indication that the limit has no longer been exceeded.