Sidebar

Home



Expressions V4


Tutorials

How-To

Reference

  Lexical basics
  Type system
  Variables and assignment
  Operators
  Expression rules
  Control flow
  Functions
  Built-in functions
   None and NaN
   Arithmetic
   Algebra
   Logarithmic and Exponential
   Trigonometric
   Rounding and Centering
   Strings
   Output, Formatting, Clipboard, and Errors
   Dialog Functions
   Platform and Paths
  Methods and properties
  Built-in methods
   Common Value Methods
   Number Methods
   String Basic Methods
   String Slice Methods
   String Parsing Methods
   String Formatting Methods
   String Regex Methods
   String Trim and Case Methods
  Objects
  Built-in objects
   Global objects
    settings
    controller
    session
    python
   Collections
    array
    map
    bytes
   File Format I/O
    image_data
    image_stream
   Utils
    crypto
    timer
   Comm
    serial
   Dialogs
    file_open
    file_save
    msg_ok
    msg_ok_cancel
    msg_yes_no
    msg_password
   GUI objects
    window
    panel
    group
    splitpanel
    label
    textbutton
    drawablebutton
    togglebutton
    togglegroup
    textinput
    textedit
    numinput
    slider
    combobox
    listbox
    progressbar
    led
    separator
    menu
    image
    snake
  Classes and user-defined objects
  Include system
  Error model
  Execution model and sessions
  Host integration
  Limits and performance
  Formal reference
  Glossary

Cookbook

exprv4:reference:control_flow



Control Flow

Control flow decides which statements are evaluated, how branches are selected, and how loops are repeated or stopped.

Expr control-flow constructs are expressions. They can be used as statements, and several of them can also produce a value.


Control-Flow Keywords

Expr supports these control-flow keywords:

  • `if`
  • `else`
  • `loop`
  • `while`
  • `for`
  • `break`
  • `continue`
  • `return`

The condition of `if`, `while`, `for`, and `loop` is written inside parentheses.

if(condition)
{
    // body
};

A control-flow construct normally ends with a semicolon when it is used as a statement.


Blocks

A block is a list of statements inside braces.

{
    a = 10;
    b = 20;
    a + b;
};

A block evaluates its statements in order. The block result is the result of the last evaluated statement, unless execution is interrupted by `return`, `break`, or `continue`.

Blocks are commonly used as the body of `if`, `loop`, `while`, and `for`.

A single statement can be used without braces, but braces are recommended for scripts that may later be edited.

if(a > 0)
    sign = 'positive';

If and Else

`if` evaluates a condition and runs a branch only when that condition is true.

if(value > 0)
{
    print('positive');
};

The condition must be inside parentheses.

Use `else` to provide a branch for the false case.

if(value >= limit)
{
    state = 'high';
}
else
{
    state = 'normal';
};

Without an `else` branch, an `if` whose condition is false produces `none()`.

result = if(false)
{
    123;
};
 
result.is_none();      // true

Else If

Expr does not have a separate `elseif` keyword.

An `else if` chain is an `else` branch that contains another `if`.

probeError = 0.03;
 
status = if(probeError <= 0.01)
{
    'excellent';
}
else if(probeError <= 0.05)
{
    'acceptable';
}
else if(probeError <= 0.10)
{
    'warning';
}
else
{
    'failed';
};

The conditions are tested from top to bottom. The first true branch is evaluated, and the remaining branches are skipped.

`else` binds to the nearest unmatched `if`.

if(a)
    if(b)
        print('a and b');
    else
        print('a and not b');

In this example, the `else` belongs to `if(b)`, not to `if(a)`.

Use braces when nested branches could be ambiguous.


If as a Value

Because `if` is an expression, it can be assigned to a variable.

message = if(toolLoaded)
{
    'Tool loaded';
}
else
{
    'No tool';
};

This is useful for selecting one value from several branches.

When an `if` is used where a value is required, provide an `else` branch unless `none()` is an acceptable result.

feed = if(material == 'aluminum')
{
    900;
}
else
{
    600;
};

Loop

`loop` repeats its body a fixed number of times.

count = 0;
 
loop(5)
{
    count += 1;
};

The count expression is evaluated once before the loop starts.

repeats = 3;
 
loop(repeats)
{
    print('step');
};

The count is converted to an integer count. A zero or negative count runs zero iterations.

loop(0)
{
    print('not printed');
};

`loop` is best when the number of repetitions is already known.


While

`while` repeats its body while its condition is true.

a = 1;
 
while(a < 10)
{
    a *= 2;
};

The condition is evaluated before each iteration. If it is false before the first iteration, the body is not evaluated.

ready = false;
 
while(ready)
{
    print('not printed');
};

A `while` loop must change something that can eventually make the condition false. Expr has safety limits for excessive loop execution, but scripts should still be written so loops finish normally.


For

`for` is a loop with initialization, condition, and iteration expressions in the header.

for(initialization; condition; iteration)
{
    // body
};

The execution order is:

  1. The initialization expression is evaluated once.
  2. The condition is evaluated before each iteration.
  3. If the condition is false, the loop stops.
  4. The body is evaluated.
  5. The iteration expression is evaluated.
  6. Execution returns to the condition check.

Example:

sum = 0;
 
for(i = 0; i < 5; i += 1)
{
    sum += i;
};

After this script, `sum` is `10`.

Any `for` header expression can be omitted.

for(; i < 10; )
{
    i += 1;
};

If the condition is omitted, the loop condition is treated as true.

for(;;)
{
    break;
};

Use `break` or another terminating condition when writing a loop without a condition.


Break

`break` exits the nearest enclosing loop.

count = 0;
 
while(true)
{
    count += 1;
 
    if(count >= 3)
    {
        break;
    };
};

After this script, `count` is `3`.

`break` is valid only inside `loop`, `while`, or `for` bodies.

In nested loops, `break` exits only the innermost loop.

outer = 0;
 
loop(3)
{
    loop(3)
    {
        break;
    };
 
    outer += 1;
};

The inner `break` does not exit the outer `loop`.


Continue

`continue` skips the rest of the current loop body and moves to the next iteration of the nearest enclosing loop.

sum = 0;
 
for(i = 0; i < 5; i += 1)
{
    if(i == 2)
    {
        continue;
    };
 
    sum += i;
};

After this script, `sum` is `8` because `2` is skipped.

`continue` is valid only inside `loop`, `while`, or `for` bodies.

In a `for` loop, the iteration expression still runs after `continue`.

for(i = 0; i < 5; i += 1)
{
    if(i < 3)
    {
        continue;
    };
 
    print(i);
};

The `i += 1` iteration expression still runs after each `continue`.


Return

`return` stops the current evaluation scope and optionally provides a value.

function Clamp01(value)
{
    if(value < 0)
    {
        return 0;
    };
 
    if(value > 1)
    {
        return 1;
    };
 
    return value;
}

`return` can be written with or without a value.

return;
return 123;

A `return` with a value returns that value. A `return` without a value returns no explicit value.

At top-level script evaluation, `return` stops evaluation of following statements.

a = 1;
return a;
a = 2;       // not evaluated

Loop Results

Loops can produce a result. The result is normally the last value produced by the body.

last = loop(3)
{
    value += 1;
    value;
};

If a loop body is not evaluated, the loop result is `none()`.

result = loop(0)
{
    123;
};
 
result.is_none();      // true

When a loop is used mainly for side effects, assign the values you need explicitly instead of relying on the loop result.


Truthiness

Control-flow conditions use Expr truthiness rules.

Common cases:

  • `false`, `0`, `none()`, and `nan()` are false.
  • `true`, non-zero numbers, non-empty strings, and objects are true.

Examples:

if(0)
{
    print('not printed');
};
 
if('text')
{
    print('printed');
};

For type-specific rules, see Type system.


Common Pitfalls

Missing Else When a Value Is Required

An `if` without an `else` can produce `none()`.

value = 10 + if(false)
{
    5;
};

Use an `else` branch when the surrounding expression needs a number, string, or object.

value = 10 + if(false)
{
    5;
}
else
{
    0;
};

Infinite Loop Conditions

This loop does not change `position`, so it cannot finish normally:

position = 0;
 
while(position < 10)
{
    print(position);
};

Update the condition variable, use `break`, or choose `loop` when the number of repetitions is fixed.

Ambiguous Nested If

Without braces, `else` binds to the nearest unmatched `if`.

if(a)
    if(b)
        print('both');
else
    print('which if?');

Use braces to make the intended branch explicit.

Previous: Expression rules

Next: Functions

exprv4/reference/control_flow.txt · Last modified: by 127.0.0.1

Page Tools