try/catch/finally is a common and familiar syntax for handling exceptions, used in many languages such as Java, C++ and Clojure. Errors thrown within the try block may be "caught" by the catch clauses. In any case, whether by normal return or exception, the finally clause is executed.
The try macro achieves a similar result. Any exceptions thrown within the try expression's body will be matched against the catch clauses in succession, returning the result of the catch clause if the exception matches. Then, regardless of means, the finally clause is executed when leaving the dynamic extent of the try expression's body.
The expressiveness of match syntax makes it sufficiently flexible for any case, and grants familiarity to those that are used to it.
Occasionally with-handlers is unwieldy. Predicates and handlers have to be wrapped in functions, and the error handling code comes before the code that can cause the error. With try it can instead be declared after, without requiring explicit lambdas:
(try
(read port)
(catch (? exn:fail:read?) #f)
Perform cleanup such as decrementing a counter on exit:
Exception-handling code is incredibly easy to get wrong. Typically it gets very little testing. with-handlers and dynamic-wind especially can be difficult to understand, and clunky to use. try/catch/finally presents a familiar syntax that is hopefully easy to use and leads to less bugs.
At the time of writing, R16 has two examples of erroneous code that could benefit from try:
This example currently doesn't handle exceptions properly.
A thread is notified and a counter incremented. A procedure that was passed in is executed, and the counter is decremented again.
However, the counter is not properly decremented for unexpected returns, such as exceptions.
This example is a simple mistake made by the author, who forgot to wrap #f in const. A read exception thrown in this causes an error trying to apply #f.
Macro
A
try
/catch
/finally
macro for "forwards" error handling and finalization. Hello #9 and #10!Source code: https://github.com/eutro/try-catch-match/blob/master/main.rkt
Documentation: https://docs.racket-lang.org/try-catch-match/index.html
try
/catch
/finally
is a common and familiar syntax for handling exceptions, used in many languages such as Java, C++ and Clojure. Errors thrown within thetry
block may be "caught" by thecatch
clauses. In any case, whether by normal return or exception, thefinally
clause is executed.The
try
macro achieves a similar result. Any exceptions thrown within thetry
expression's body will bematch
ed against thecatch
clauses in succession, returning the result of thecatch
clause if the exception matches. Then, regardless of means, thefinally
clause is executed when leaving the dynamic extent of thetry
expression's body.The expressiveness of
match
syntax makes it sufficiently flexible for any case, and grants familiarity to those that are used to it.The
try-with
macro (and its cousintry-with*
), influenced bywith-open
from Clojure and thetry-with-resources
from Java generalises resource cleanup in an exception-safe way.Example
Occasionally
with-handlers
is unwieldy. Predicates and handlers have to be wrapped in functions, and the error handling code comes before the code that can cause the error. Withtry
it can instead be declared after, without requiring explicit lambdas:Perform cleanup such as decrementing a counter on exit:
Open a file and close it on exit:
Before and After
Exception-handling code is incredibly easy to get wrong. Typically it gets very little testing.
with-handlers
anddynamic-wind
especially can be difficult to understand, and clunky to use.try
/catch
/finally
presents a familiar syntax that is hopefully easy to use and leads to less bugs.At the time of writing, R16 has two examples of erroneous code that could benefit from
try
:This example currently doesn't handle exceptions properly. A thread is notified and a counter incremented. A procedure that was passed in is executed, and the counter is decremented again. However, the counter is not properly decremented for unexpected returns, such as exceptions.
It could be rewritten with
dynamic-wind
, which may confuse those unfamiliar with it.Or with
try
:This example is a simple mistake made by the author, who forgot to wrap
#f
inconst
. A read exception thrown in this causes an error trying to apply#f
.It could be rewritten with
try
, without requiring aconst
, as:Licence
This code is under the same MIT License that the Racket language uses. https://github.com/eutro/try-catch-match/blob/master/LICENSE The associated text is licensed under the Creative Commons Attribution 4.0 International License http://creativecommons.org/licenses/by/4.0/