An implementation of Common Lisp dynamic variables, control flow operators, and condition system in plain Java.
"We were not out to win over the Lisp programmers; we were after the C++ programmers. We managed to drag a lot of them about halfway to Lisp."
--- Guy Steele, Java spec co-author
"Notice that no one mentions that this way they also managed to drag a lot of Lisp programmers about halfway back to C++."
--- Michał "phoe" Herda, angry Internet rando
This is an implementation of Common Lisp dynamic variables, control flow operators, and condition system in plain Java.
If Portable Conditon System is a proof that a Common Lisp condition system can be implemented on a Common Lisp implementation without a condition system of its own, then Cafe Latte is a proof that a Common Lisp-inspired condition system can be implemented even on top of a non-Lisp language that has only automatic memory management and a primitive unwinding operator (in this case, throw
), but does not support dynamic variables or non-local returns by default.
It should be possible to use it, or parts of it, in other projects, and its source code should be readable enough to understand the underlying mechanics of each Lisp control flow operator.
This library is not yet documented, but the respective implementations should behave analogously to their Common Lisp counterparts; see the Common Lisp HyperSpec for their descriptions.
Example uses of the various constructs implemented here are present in the test directory, containing unit tests for all the present mechanisms.
A stable release of this library will be made when the authors are satisfied enough with its functioning.
AGPLv3. (Unless you are @easye, at which point it's whatever license suits you the best.)
DynamicVariable
class.tagbody
/go
Tagbody
class.block
/return-from
Block
class.throw
/catch
catch
/throw
are renamed to grasp
/fling
.Grasp
class.throw
/catch
are not required for implementing a condition system, but their implementations are nonetheless included here for completeness.Condtion
class.RuntimeException
.superFillInStackTrace()
method.Warning
class.Condition
.Error
class.Condition
.Handler
class.signal
Handler
class as a static method.warn
Handler
class as a static method.error
Handler
class as a static method.*break-on-signals*
Handler
class as a dynamic variable.handler-bind
HandlerBind
class.handler-case
HandlerCase
class.ignore-errors
HandlerCase
class as a static method.Restart
class.restart-bind
RestartBind
class.restart-case
RestartCase
class.with-simple-restart
RestartCase
class as a static method.Debugger
class.*debugger-hook*
Debugger
class as a dynamic variable.break
Debugger
class as a static method.break
is renamed to breakIntoDebugger
.NoDebugger
class.Error
class by means of calling the static error
method.toString
mechanism.toString
mechanism.unwind-protect
- Java has try
/finally
that is fully equivalent.