Table of Contents

How To Handle Missing And Invalid Values

Real scripts often need to deal with values that are missing, invalid, or unsafe to use.

Common cases:

Expr gives you several tools for this:


Missing Values: none()

`none()` means no value.

value = none();
value.is_none();

Reading an unknown variable also returns `none()`.

missing_value;

This lets a script check whether something is available before using it.

if(missing_value.is_none())
{
    print('value is missing');
};

`none()` is not the same as `0` or an empty string.

none() == 0;     // false
none() == '';    // false

Check Before Calculating

Do not use `none()` in numeric calculations.

5 + none();      // error

Check first:

tool_diameter = none();
 
if(tool_diameter.is_none())
{
    print('tool diameter is missing');
}
else
{
    radius = tool_diameter / 2;
    print('radius ', radius);
};

If the value is required, stop with an error instead of continuing.

if(tool_diameter.is_none())
{
    error('Tool diameter is required');
};

Invalid Numbers: nan()

`nan()` means not a valid number.

value = nan();
value.is_nan();

NaN is different from `none()`. It is a numeric invalid value, not a missing value.

Use `.is_nan()` when you specifically want to detect NaN.

if(value.is_nan())
{
    print('invalid number');
};

For most practical checks, use `.is_num_notnan()` when a value must be a usable number.

if(value.is_num_notnan())
{
    print('usable number');
};

Require A Usable Number

Use `.is_num_notnan()` before numeric operations when the value may come from input, a file, a dialog, or another script.

feed = 800;
 
if(!feed.is_num_notnan())
{
    error('Feed must be a valid number');
};
 
if(feed <= 0)
{
    error('Feed must be positive');
};

This protects later calculations from bad input.


Avoid Division By Zero

Division by zero and modulo by zero are errors.

10 / 0;     // error
10 % 0;     // error

Check the divisor first.

function DivideOrNone(a, b)
{
    if(b == 0)
    {
        return none();
    };
 
    return a / b;
}
 
result = DivideOrNone(10, 0);

Use `none()` when the caller can continue without a value. Use `error(…)` when the script should stop.

function DivideRequired(a, b)
{
    if(b == 0)
    {
        error('Division by zero');
    };
 
    return a / b;
}

Parse Text Safely

Parsing methods such as `.parse_num()` raise an error when the text is not valid.

'123'.parse_num();    // 123
'abc'.parse_num();    // error

If the text may be invalid, check it before parsing or handle it in a function with a clear error message.

function ParsePositiveNumber(name, text)
{
    if(text.is_none() || text.length() == 0)
    {
        error(name, ' is missing');
    };
 
    set value = text.parse_num();
 
    if(!value.is_num_notnan() || value <= 0)
    {
        error(name, ' must be positive');
    };
 
    return value;
}
 
feed = ParsePositiveNumber('Feed', '800');

This function gives a better message than a later calculation failure.


Use Defaults Only When Safe

Sometimes a missing value can use a safe default.

clearance = none();
 
if(clearance.is_none())
{
    clearance = 5;
};

Use defaults for harmless settings. Do not silently default values that affect safety unless that is the intended machine behavior.

For required values, prefer `error(…)`.

if(tool_number.is_none())
{
    error('Tool number is required');
};

Handle Optional Results

Functions can return `none()` when no result is found.

function FindToolName(number)
{
    if(number == 1)
    {
        return 'T1';
    };
 
    if(number == 2)
    {
        return 'T2';
    };
 
    return none();
}
 
tool_name = FindToolName(5);
 
if(tool_name.is_none())
{
    print('tool not found');
}
else
{
    print('tool ', tool_name);
};

This is useful when not finding a value is allowed.


Stop Early With error()

Use `error(…)` when continuing would be unsafe or misleading.

function RequireSafeZ(value)
{
    if(!value.is_num_notnan())
    {
        error('Safe Z must be a number');
    };
 
    if(value <= 0)
    {
        error('Safe Z must be above zero');
    };
 
    return value;
}
 
safe_z = RequireSafeZ(5);

A clear error is better than a script that continues with bad data.


Use Checks From MDI

In MDI, start with `=` to evaluate Expr.

=feed='800';
value=feed.parse_num();
if(value <= 0)
{
    error('Feed must be positive');
};
value;

The final result is `800`.


Common Mistakes

Treating none() Like Zero

value = none();
result = value + 5;    // error

Check first or provide a safe default.

Ignoring nan()

NaN often spreads through calculations.

value = nan();
result = value + 10;
result.is_nan();       // true

Use `.is_num_notnan()` when you need a usable number.

Using Defaults For Required Safety Values

This may hide a setup problem:

if(tool_diameter.is_none())
{
    tool_diameter = 6;
};

If the operator or job must provide the value, stop instead:

if(tool_diameter.is_none())
{
    error('Tool diameter is required');
};

Letting A Parse Error Happen Later

Parse and check input close to where it enters the script.

feed_text = '800';
feed = feed_text.parse_num();
 
if(feed <= 0)
{
    error('Feed must be positive');
};

Try This

In MDI, try:

=tool_diameter=none();
if(tool_diameter.is_none())
{
    'missing diameter';
}
else
{
    tool_diameter / 2;
};

The final result is `'missing diameter'`.


See Also


Previous: Show output and debug scripts

Next: Work with arrays and maps

How-To index: How-To Guides