Nasal scripting language: Difference between revisions

Jump to navigation Jump to search
Line 731: Line 731:


[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]
[[Nasal_scripting_language#settimer.28.29|More information about the settimer function is below]]
== Exception handling ==
<tt>die()</tt> aborts a function with an error message (this can be compared to the throw() mechanism in C++).
var divide = func(a, b) {
    if (b == 0)
        die("division by zero");
    return a / b;    # this line won't be reached if b == 0
}
die() is also used internally by built-in extension functions or Nasal core functions. <tt>getprop("/4me")</tt>, for example, dies with an error message ''"name must begin with alpha or '_'"''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to <tt>getprop()</tt>? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The <tt>call()</tt> function can catch <tt>die()</tt> exceptions:
var value = getprop(property);                                    # dies if 'property' is invalid
var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the <tt>call()</tt> function catches the exception and sets the 'err' vector instead. That vector remains empty on success.
if (size(err))
    print("ERROR: bad property ", property, " (", err[0], ")");  # err[0] contains the die() message
else
    print("value of ", property, " is ", value);
The first argument of <tt>call()</tt> is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the <tt>call()</tt> function see the [http://plausible.org/nasal/lib.html Nasal library documentation].
<tt>die()</tt> doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.
var Error = {                                                            # exception class
    new: func(msg, number) {
        return { parents: [Error], message: msg, number: number };
    },
};
var A = func(a) {
    if (a < 0)
        die(Error.new("negative argument to A", a));                      # throw Error
    return "A received " ~ a;
}
var B = func(val) {
    var result = A(val);
    print("B finished");      # this line is not reached if A threw an exception
    return result;
}
var value = call(B, [-4], var err = []);                                  # try B(-4)
if (size(err)) {                                                          # catch (...)
    print("ERROR: ", err[0].message, "; bad value was ", err[0].number);
    die(err[0]);                                                          # re-throw
} else {
    print("SUCCESS: ", value);
}


== Listeners and Signals ==
== Listeners and Signals ==

Navigation menu