|
|
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 == |