Error Handling
[1/5] from: anton::lexicon::net at: 10-Dec-2002 21:21
I use error trapping all the time, but
only where I find it necessary or where
I suspect that the code may break.
It doesn't get too much in the way.
Anton.
[2/5] from: rebol-list2:seznam:cz at: 9-Dec-2002 21:15
Hello Rod,
Sunday, December 8, 2002, 8:53:01 PM, you wrote:
RG> Following on from Ladislav's request for
>> "The interpreter should not have any crashes at all"?
RG> here are some questions and thoughts on error handling
RG> in REBOL.
RG> Questions -
RG> 1. Who is using try, disarm and the error! object?
I do it very often.
For example this is from my recent IRC client:
try-do: func[action][if error? set/any 'err try [do action][bot-error disarm err]]
bot-error: func[err /local type id arg1 arg2 arg3][
set [type id arg1 arg2 arg3] reduce [err/type err/id err/arg1 err/arg2 err/arg3]
cprint/err [
"Bot-" system/error/:type/type ": "
reduce bind system/error/:type/:id 'arg1
]
cprint/err ["** Where: " mold err/where]
cprint/err ["** Near: " mold err/near]
]
=( Oliva David )=======================( [oliva--david--seznam--cz] )==
=( Earth/Europe/Czech_Republic/Brno )=============================
=( coords: [lat: 49.22 long: 16.67] )=============================
[3/5] from: brett:codeconscious at: 11-Dec-2002 12:12
Hi Rod,
> 1. Who is using try, disarm and the error! object?
>
> I haven't yet written anything for someone else in REBOL
> and thus haven't dug into them myself.
I do occasionally. I haven't used error handling as much as I should have.
Initially I was being lazy in trying to understand what was available to me
and how I wanted to use it.
> 2. If you are using the error handling features what are
> your opinions of them?
<<quoted lines omitted: 4>>
> 1. I don't generally like the "try" approach in managing
> errors.
I met a "try" approach with Delphi. I loved this because it was the first
time I had real confidence that if I wanted to catch everything, I could.
After my experience with Try in Delphi I was glad when I saw TRY in REBOL.
> It seems that to do it with any thoroughness you
> have to "litter" your program logic with distracting bits of
> tests and syntax.
>From my point of view, errors are part of the variety in the problem space
our programs have to deal with. So they have to be managed somewhere. If I
want to make resuable code, the bit that "makes sense" of the error really
needs to be "close" to the bit that handles the code that generated the
error. So I feel what seems like "litter" and what is does not depends on
your application and its purpose.
> In the case of such a dynamic language
> as REBOL you may be able to mitigate that effect by using
> more data to code processing that puts that extra syntax
> in there for you. Another option would be to replace key
> language constructs with ones that conform to your own
> framework and error handling setups.
It makes sense to have a reusable error handling methods/constructs for
specific situations.
> 2. What I would like to see is an event driven approach to
> errors. The environment could define specific error types
<<quoted lines omitted: 4>>
> done yet the handling doesn't intrude on the logic and
> syntax of the normal processing.
Delpi had a TRY / EXCEPT construct. The code in the TRY was performed and if
an error was generated it could possibly be trapped by a handler in the
Except. The Except could have multiple handlers - which would react based on
the class of the error. Unhandled exceptions would bubble out. Errors could
be re-raised allowing local handling of resources and then higher level
handling as well. 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.
In my opinion this scheme worked fairly well. Exceptions relevent to the
code would be handled near the code, other stuff would be handled further
up. At the very top level of my application I would have a catch-all
handler. Any errors making it this far up were pretty much application
errors. In any case, the application never failed for the user.
Regards,
Brett.
[4/5] from: rgaither:triad:rr at: 11-Dec-2002 9:37
Hi All,
Thanks to everyone who gave some insight into their use of
the error handling options in REBOL. It has helped me get
off square one about what approach options are available.
Thanks, Rod.
On Tuesday, December 10, 2002, at 08:12 PM, Brett Handley wrote:
> Hi Rod,
>> 1. Who is using try, disarm and the error! object?
<<quoted lines omitted: 78>>
> [rebol-request--rebol--com] with "unsubscribe" in the
> subject, without the quotes.
Rod Gaither
[rgaither--triad--rr--com]
Oak Ridge, NC USA
[5/5] 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
]
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted