Conditional Constructs

Summary:
The Curl® language includes five conditional expressions: if, if-non-null, unless, switch and type-switch.
This chapter describes the conditional expressions in the Curl language. When the Curl® Runtime Environment (RTE) encounters a conditional expression, it evaluates the Boolean expression and, if the condition is met, it evaluates the enclosed code. The Curl language includes the following conditional expressions:

if Expression

Summary:
  • If a condition is true, evaluate one or more expressions.
  • Optionally specify expressions to evaluate if the condition is not true.
You can use the if expression to tell the Curl RTE to execute code when a condition is true. The if expression also provides clauses for specifying code to execute if the condition evaluates to false. There are three forms of the if expression:

if Expression

In its simplest form, the if expression executes code when a Boolean expression is true. This form of the if expression has the following syntax:
Syntax:{if condition then
    code-block
}
where:
conditionis a Boolean expression.
code-blockconsists of one or more Curl language expressions.
When the Curl RTE encounters such an if expression, it evaluates condition. If condition is true, the RTE executes code-block. Otherwise, it does not execute code-block and moves to the end of the if expression.
Note: This form of the if expression (that does not have an else clause) does not produce a value. If you attempt to use an if expression that does not have an else clause in a situation that requires a value, you will generate a syntax error.

Example: An if Expression
{value
    || Declares two integers "x" and "y".
    || Initializes "x" to 1 and "y" to 2.
    || Define a variable "message" to be a vertical box.
    || In this example, "message" is used to store a
    || string that will later be displayed.
    let x:int=1
    let y:int=2
    let message:VBox={VBox}

    || If "x" is greater than or equal to "y" then
    || place an appropriate string in message.
    || Note that "add" is a method of VBox.
    {if x >= y then
        {message.add "x is greater than or equal to y!"}
    }

    || If "x" is less than "y" then
    || place a different string in "message".
    {if x < y then
        {message.add "x is less than y!"}
    }

    || Display the contents of "message".
    message
}

if Expression with else Clause

In this form, the if expression executes certain code when a Boolean expression is true and other code when the Boolean expression is false. The if ... then ... else ... form has the following syntax:
Syntax:{if condition then
    code-block-1
 else
    code-block-2
}
where:
conditionis a Boolean expression.
code-block-1 and code-block-2each consist of one or more Curl language expressions.
When the RTE encounters such an if expression, it evaluates condition. If condition is true, the RTE executes code-block-1 and then moves to the end of the if expression (skipping code-block-2). If condition is false, it skips code-block-1, executes code-block-2, and then moves to the end of the if expression.

Example: An if Expression with else Clause
{value
    || Define and initialize two integer variables: x=1,
    || y=2.  Define a vertical box variable "message" to
    || store and display a string.
    let x:int=1
    let y:int=2
    let message:VBox={VBox}

    || If "x" is greater than or equal to "y" then place
    || an appropriate string in "message" otherwise,
    || place a different string in "message".
    {if x >= y then
        {message.add "x is greater than or equal to y!"}
     else
        {message.add "x is less than y!"}
    }

    || Display the contents of "message".
    message
}
If all branches of an if expression produce values, the if expression as a whole produces a value. In particular, the if expression produces the value of the branch that is executed.

Example: An if Expression that Produces a Value
{value
    || Define and initialize two integer variables: x=1,
    || y=2.
    let x:int=1
    let y:int=2

    || Define a vertical box variable "message" to store
    || and display a string.  If "x" is greater than or
    || equal to "y" then assign an appropriate VBox to
    || "message" otherwise, assign a different VBox to
    || "message".
    let message:VBox = {if x >= y then
                           {VBox "x is greater than or equal to y!"}
                        else
                           {VBox "x is less than y!"}
                       }

    || Display the contents of "message".
    message
}

if Expression with elseif Clause

Within an if expression, you can have another if expression as the body of the else clause. To help with readability, the Curl language includes a special syntax for this:
Syntax:{if condition-1 then
    code-block-1
 elseif condition-2 then
    code-block-2
 elseif condition-3 then
    code-block-3
 ...
 elseif condition-n then
    code-block-n
 [else
    code-block-n+1]
}
where:
condition-1, condition-2, ...are Boolean expressions.
code-block-1, code-block-2, ...each consist of one or more Curl language expressions.
When the RTE encounters such an if expression, it evaluates condition-1. If condition-1 is true, the RTE executes code-block-1 and then moves to the end of the if expression (skipping the other clauses). If condition-1 is false, it evaluates condition-2. If condition-2 is true, the RTE executes code-block-2 and then moves to the end of the if expression. If condition-2 is false, it evaluates condition-3. If condition-3 is true, the RTE executes code-block-3 and then moves to the end of the if expression. This continues until one of the conditions evaluates to true or the RTE reaches the optional else clause. If the else clause exists and it reaches it without evaluating one of the conditions to true, the RTE executes code-block-n+1.

Example: An if Expression with elseif Clause
{value
    || Define and initialize two integer variables: x=1,
    || y=2.  Define a vertical box variable "message" to
    || store and display a string.
    let x:int=1
    let y:int=2
    let message:VBox={VBox}

    || If "x" is equal to "y" then
    || place an appropriate string in "message"
    || otherwise, if "x" is greater than "y"
    || place an appropriate string in "message"
    || otherwise
    || place a different string in "message"
    {if x == y then
        {message.add "x is equal to y!"}
     elseif x > y then
        {message.add "x is greater than y!"}
     else
        {message.add "x is less than y!"}
    }

    || Display the contents of "message"
    message
}

if-non-null Expression

The if-non-null construct provides a construct that allows you to combine conditional evaluation like {if {non-null expr} then if-body} with a cast of the test expression to a non-null value.
This expression is described in more detail in the section if-non-null.

unless Expression

Summary:
  • If a condition is not true, evaluate one or more expressions.
The functionality offered by the unless expression is similar to the functionality offered by the if expression. Both expressions provide a way to execute code when a condition is met. However, in the case of unless, the RTE executes the code when the Boolean expression evaluates to false. In other words, the unless expression is similar to if (not ...) then .... Also, unlike the if expression, the unless expression does not provide a way to specify alternative code to execute when the condition is not met. The unless expression has the following syntax:
Syntax:{unless condition do
    code-block
}
where:
conditionis a Boolean expression.
code-blockconsists of one or more Curl language expressions.
When the RTE encounters an unless expression, it evaluates condition. If condition is false, the RTE executes the code-block. Otherwise, it does not execute the code-block and moves to the end of the unless expression.
Note: An unless expression does not return a value. The RTE evaluates the conditions and, if appropriate, evaluates the statements and expressions in the enclosed code block. However, the unless expression itself does not return a value.

Example: An unless Expression
{value
    || Define and initialize two integer variables: x=1,
    || y=2.  Define a vertical box variable "message" to
    || store and display a string.
    let x:int=1
    let y:int=2
    let message:VBox={VBox}

    || Place a string of explanatory text in "message".
    {message.add "If the condition is false, a message appears..."}

    || Place an appropriate string in message if "x" is
    || NOT greater than or equal to "y".
    {unless x >= y do
        {message.add "x is less than y!"}
    }

    || Display the contents of "message".
    message
}
The unless construct is less useful overall than the if construct, and the differences between the two can result in in confusing code. It is recommended that you ignore unless and use only if.

switch Expression

Summary:
  • Compares an expression with a number of values and then execute the code for the value that matches.
  • By default uses the equality comparison operator (==).
  • You can override the default comparison operator.
The switch expression allows you to compare a given expression to a number of values. Each value has associated code. The RTE executes the code that corresponds to the first value that matches the given expression. It compares the values in the order that they are presented in the code. The switch expression also allows you to specify code to execute if there is no matching value.
The switch expression has the following syntax:
Syntax:{switch compare-expr [complete] [using compare-operator]
  case value-1 do
    code-block-1
  case value-2, value-3 do
    code-block-2
  ...
  case value-n do
    code-block-n
  [else code-block-n+1]
}
where:
compare-expr, value-1, value-2, ...are Curl language expressions. These expressions can evaluate to any Curl language type, including int, float, char, bool, String, enumerated types, and user-defined classes.
compare-operatoris the operator that the Curl language uses when comparing compare-expr to value-1, value-2, and so on. By default, the switch expression uses the equality comparison operator (==). The other comparison operators are !=, >, >=, <, <=, and isa.
code-block-1, code-block-2, ...consist of one or more Curl language expressions.
By default, the switch expression uses the equality operator, == to perform the comparison. The using keyword lets you specify a different comparison operator. For example, you can use the greater than operator, > or even the type comparison operator, isa.
You can use the complete keyword only if value is an enumerated type. It causes an error if any of the possible values is omitted from the case clauses. Both the using and else clauses are optional.
When the RTE encounters a switch expression, it compares the value of compare-expr with each of value-1, value-2, and so on. When the RTE encounters the first comparison that returns a true value, it executes the code that follows the accompanying do keyword, then moves to the end of the switch expression. If none of the comparisons return a true value and there is an else clause, the RTE executes the code that follows the else clause. If there is no else clause, it moves to the expression immediately following the switch expression.
Like the if expression, if the switch contains an else clause and all the branches of a switch expression produce values, then the switch returns the value of the last expression that it evaluates. Otherwise, the expression does not return a value, with one exception: if the compile-time type of the compare-expr is an enumerated type and all of its elements are included in the cases, then the else clause may be omitted since it is known that it can never be invoked.
The following example illustrates the switch expression. Each execution of the loop compares a different value of the variable y to several values. The switch expression executes code associated with each value of y.

Example: A switch Expression
{value
    let message:VBox={VBox}
    {for y:int = 0 to 3 do
        {switch y
         case 0 do
            {message.add "y is equal to 0!"}
         case 1 do
            {message.add "y is equal to 1!"}
         case 2 do
            {message.add "y is equal to 2!"}
         else
            {message.add "y is greater than 2!"}
        }
    }
    message
}
If you want to execute the same code for two or more values, place the values in the same case clause and use commas to separate them. The following example compares y to 0 and 1 in a single case clause, and returns the same message for either value.

Example: Executing the Same Code for Two or More Values
{value
    let message:VBox = {VBox}
    {for y:int = 0 to 3 do
        {switch y
         case 0, 1 do
            {message.add "y is less than 2!"}
         case 2 do
            {message.add "y is equal to 2!"}
         else
            {message.add "y is greater than 2!"}
        }
    }
    message
}
In the following example, the using keyword specifies how switch performs the comparison. It uses the operator isa to compare the type of the variable y to types provided in the case clauses.

Example: The optional using clause specifying the comparison operator
{value
    let y:int
    let message:Frame = {Frame}
    {switch y using isa
     case bool do
        {message.add "y is a Boolean!"}
     case char do
        {message.add "y is a character!"}
     case int8, int16, int32, int64, int, uint8, uint16 do
        {message.add "y is an integer!"}
     case float, double do
        {message.add "y is a floating-point number!"}
     else
        {message.add "y is not a simple primitive value!"}
    }
    message
}
For more details, including discussion of the complete keyword, see: switch.

Specialized Switch Expressions

The type-switch expression uses the data type of a value to determine which block of code to execute. This expression is described in Working with Data Types: The type-switch Expression. The platform-switch expression supports conditional compilation based on the current platform. For more information on using platform-switch see Writing Cross-platform Applets.