[REBOL] Re: Error Handling
From: brett:codeconscious at: 22-Dec-2002 23:19
I wrote sometime ago:
> I don't think it would be too difficult to add a
> try-except to REBOL. I suspect it would be possible to make it a mezzanine
> too.
And Maarten's post of Ernie's HANDLE showed some it. Some very handy stuff
too which made me think some more on error handling ideas. Here's a few
variants that might be interesting. They are obviously exploratory ideas not
long-time tested concepts/scripts. Not sure of the usefulness of them but
here they are...
Sorry about line-wrapping of my verbose function doco.
; 8<------------------------------------------------------
REBOL [
Title: "Error handling possibilities."
Author: "Brett Handley"
]
on-error: func [
{Tries to DO a block or if an error DO handler.}
[catch]
block [block!]
handler "If handler is a block! then ERROR, RESULT, BLOCK and HANDLER
will be bound."
/local result error
] [
if error? set/any 'result try block [
if block? :handler [
error: disarm result
bind handler 'result
]
set/any 'result do handler
]
get/any 'result
]
any-success: func [
{Tries to DO each block of a series and returns the first value that is
not an error.}
[catch]
block [any-block!]
/local result
] [
result: none
repeat expression block [
if not error? set/any 'result try expression [break]
]
get/any 'result
]
until-success: func [
{Tries to DO the block and will continue retrying until the evaluation
completes without an error.}
[catch]
block [any-block!]
delay [time! block! none!] "Delay time or expression to DO before trying
again."
/local result
] [
if time? delay [delay: does compose [wait (delay)]]
result: none
forever [
if not error? set/any 'result try block [break]
do delay
]
get/any 'result
]
; 8<------------------------------------------------------
; EXAMPLES
; ON-ERROR
; A (smaller) variation on Ernie's HANDLE. It allows the
; handler block to return a value.
; The handler just eats the error
on-error [1 / 0] []
; The handler returns a value where the first block fails.
on-error [1 / 0] none
on-error [1 / 0] ["Success"]
; The handler re-raises the original exception.
on-error [1 / 0] [
print "do something important."
result
]
; The handler has access to the disarmed error and
; Reinterprets math errors into a user error, other
; errors are just re-raised. A function is used here
; to demonstrate both cases.
test-func: func [code] [
on-error code [
either error/type = 'math [
make error! "You shoulda saw that coming!"
] [result]
]
]
test-func [Print "math error" 1 / 0]
test-func [Print "bad arg type" read [asdfjkl--lksdfkl]]
; ANY-SUCCESS
; Try a few things - one of them should work...
any-success [
[1 / 0]
[read [asdfjkl--lksdfkl]]
["Success"]
]
; UNTIL-SUCCESS
; A simple delay, until finally success.
k: 0
until-success [
print "trying..."
if lesser? k: k + 1 4 [1 / 0]
"Success!"
] 00:00:01
; A complex delay.
; Breaking from the delay block returns the last error.
k: 0
until-success [print "Trying..." 1 / 0] [
if greater? k: k + 1 4 [break]
wait 00:00:01
]