Is there a 'best' way to exit functions?
pokeeffe
For errors, a simple Abort with message seems appropriate. For 'Cancel' buttons, I can't decide which is better - perhaps return is so that calling functions have a chance to continue? Does anyone have a good understanding of why you might choose one over the other?
// typical exit if user cancels DoPrompt
If (V_flag)
return -1 // returns -1
endif
// quicker exit
AbortOnValue V_flag, -1 // returns NAN
// need to return user home
If (V_flag)
SetDataFolder sav0
return -1 // this one
//AbortOnValue 1, -1 // or this one?
endif
If (V_flag)
return -1 // returns -1
endif
// quicker exit
AbortOnValue V_flag, -1 // returns NAN
// need to return user home
If (V_flag)
SetDataFolder sav0
return -1 // this one
//AbortOnValue 1, -1 // or this one?
endif
For other situations, you should return an error code that the calling routines can interpret. We use 0 to mean success and non-zero to mean failure. -1 is usually used to mean cancel. The calling routine can then decide whether to retry, abort or return the error code to its calling routine.
April 1, 2011 at 08:06 pm - Permalink
Tester(2) // Transfers control to a catch block
Print "Starting Test1"
// AbortOnValue outside of a try-catch block aborts procedure execution
AbortOnValue 1, 1234
Print "Finished Test1" // Will never execute
End
Function Test2()
Print "Starting Test2"
// AbortOnValue inside of a try-catch block tranfers control to the catch block
try
AbortOnValue 1, 1234
catch
Printf "An error was thrown with code %d\r", V_abortCode
endtry
Print "Finished Test2"
End
Function Tester(which)
Variable which // 1 for Test1, 2 for Test2
Print "Starting Tester"
switch(which)
case 1:
Test1()
break
case 2:
Test2()
break
endswitch
Print "Finished Tester"
End
April 2, 2011 at 02:28 pm - Permalink
If I want to alert the user to a problem, I'll use DoAlert to present a simple message, and then use Howard's idea of returning a simple success/fail/cancel value.
I haven't used Abort for 15 years.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
April 2, 2011 at 10:41 pm - Permalink
I partially agree, partially disagree with this. I'd deepen your statement to say that Abort should never be part of any program flow that you expect the user to reach. That means that, if your program executes perfectly (no bugs), no Abort statements should ever be executed.
I tend to sprinkle quite a few Abort statements into my code to aid me in catching possible bugs. Basically, if I know that something should never occur, then I'll add in that case and have it trigger an Abort statement. An example here would be adding a default statement in a switch statement even where I don't expect one to be necessary. Example:
strswitch(color)
case "green":
case "blue":
case "red":
//do something
break
default:
Abort "Invalid input \"" + color "\" to strswitch at blah"
break
endswitch
The idea here is that, when my program enters undefined territory, I would like it to blow up as soon as possible and as irreversibly as possible.
April 3, 2011 at 05:57 pm - Permalink
741, that's an excellent idea for catching bugs - simple & informative!
April 4, 2011 at 01:54 pm - Permalink
If I'm developing code that I plan to not give to anyone else, I'd be okay with that. But code the user "should never reach" has a way of reaching users. So I'd rather use:
DoAlert 0, "invalid input..."
return errorCodeThatAllowsMeToLimpAlongGracefully
Remember, Abort alters the control flow, often in ways that may surprise you.
--Jim Prouty
Software Engineer, WaveMetrics, Inc.
April 5, 2011 at 02:18 pm - Permalink