Page 1 of 1

Proper script writing: throwing errors within UDFs

Posted: 30 Apr 2015 18:29
by Marco
Today I just tested the waters when it comes to UDFs, and I'd like to know what's the proper way to throw errors in an UDF.

First, a little observation: something like this

Code: Select all

 $x = formatdate(gttw3tw);
throws an error at formatdate() in the "script console", and then continues setting the variable to nothing.

TheQwerty suggests using assert, which takes an optional "continue" flag. Setting it it's like no "real" error is thrown at all, because the UDF continues. Not setting the "continue" flag terminates the whole script instead.
Then there's end, which is more granular because it allows to abort the UDF without terminating the whole script, however it throws a warning with a popup window, which is not consistent with a "genuine" function error.

So, how can I throw an error in a UDF which
-makes the script console pop up
-aborts the rest of the UDF
-continues executing the rest of the calling script,
much like an XY function?

Re: Proper script writing: throwing errors within UDFs

Posted: 30 Apr 2015 18:43
by bdeshi
when does end throw a popup window? end 1,,1;

you can put a conditional return; after the assert cmd.

Re: Proper script writing: throwing errors within UDFs

Posted: 30 Apr 2015 18:56
by TheQwerty
It really depends on what the function is doing.

One way:

Code: Select all

function crappyFunction($a) {
  $badCondition = ($a == '' || $a != ''); // Whatever your test expression is, and you could just put it in the if instead. ;)
  if ($badCondition) {
    Assert false, 'Bad happened.', true;
    return ''; // or -1, or another value that makes sense.
  }

  return 'all good';
}
Another would be to replace the assert with an echo and use the undocumented bits (icon 4,7,8, or 9 are okay options).

I prefer to avoid popping up a dialog though by documenting assumptions and returning error codes - putting the decision and work on the caller instead.

When it comes to returning errors we've got options:
false (Empty String or 0)
-1
Something like WriteFile/Exists: 0|msgOrReturnValue
Pass a variable via reference instead:

Code: Select all

// Returns a greeting or false (error) if $input is empty.
function hello($input) {
  if ($input == '') {
    Assert false, 'Empty', true';
    return false;
  }
  return "Hello $input";
}

// Sets result to the greeting return false (error) if $input is empty.
function hello(&$result, $input) {
  $result = "Hello $input";
  return $input != '';
}

Re: Proper script writing: throwing errors within UDFs

Posted: 30 Apr 2015 19:08
by bdeshi
talking of variables, I'm test-driving a global $lasterr mechanism.
Sometimes '' can be a valid return but it can also be the same when an error ocurred. $lasterr can say what really happened.

Code: Select all

function f($var){
  global $lasterr = '';
  $return = replace($var,$var);
  //  processing
  if ($var == 'bad') { $lasterr = 'BADVER'; }
  return $return;
}
"test"
 $f = f('bad');
 if ($lasterr != '') { echo 'f() : I Am ERRor! (a pointless one)'; }
But those conditions may have to be put before/after every command/block for 100% error-catching.

There should be something native and simpler like this.

Re: Proper script writing: throwing errors within UDFs

Posted: 01 May 2015 16:25
by bdeshi
To babble on...

http://www.xyplorer.com/xyfc/viewtopic. ... 22#p122921 I used the aforementioned method here. Works nicely but it breaks down if a function is called from another function. Because the inner function can overwrite the outer's (non-fatal) errors.

Can there be a special error receiver variable or sth?
Say, like this:

Code: Select all

echo $err::int(); //returns the last error triggered from int().
FUNCTION int() {
 //code code
 if !(condition) { $err::() = self('caption') . '() errored'; }
 //^ records an error from this function (the ::() denotes $err var for current function ;) )
 //code code
just a suggestion.