"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.
It started out as a proof that a condition system can be implemented even on top of a language that has only automatic memory management and a primitive unwinding operator (throw), but does not have 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.)
- Dynamic variables
- Dynamic variable class
- Implemented in the
DynamicVariableclass. - Unit tests done.
- Implemented in the
- Dynamic variable class
- Control flow
-
tagbody/go- Implemented in the
Tagbodyclass. - Unit tests done.
- Implemented in the
-
block/return-from- Implemented in the
Blockclass. - Unit tests done.
- Implemented in the
-
throw/catch- Because of Java naming conflicts,
catch/throware renamed tograsp/fling. - Implemented in the
Graspclass. - Unit tests done.
throw/catchare not required for implementing a condition system, but their implementations are nonetheless included here for completeness.
- Because of Java naming conflicts,
-
- Conditions
- Condition class
- Implemented in the
Condtionclass. - Subtype of
RuntimeException. - Do not fill in the stack trace when instantiated; see the
makeReadyToThrow()method.
- Implemented in the
- Warning class
- Implemented in the
Warningclass. - Subtype of
Condition.
- Implemented in the
- Error class
- Implemented in the
Errorclass. - Subtype of
Condition.
- Implemented in the
- Condition class
- Handlers
- Handler class
- Implemented in the
Handlerclass. - Tested elsewhere.
- Implemented in the
-
signal- Implemented in the
Handlerclass as a static method. - Tested elsewhere.
- Implemented in the
-
warn- Implemented in the
Handlerclass as a static method. - Unit tests done.
- Implemented in the
-
error- Implemented in the
Handlerclass as a static method. - Unit tests done.
- Implemented in the
-
handler-bind- Implemented in the
HandlerBindclass. - Unit tests done.
- Implemented in the
-
handler-case- Implemented in the
HandlerCaseclass. - Unit tests done.
- Implemented in the
-
ignore-errors- Implemented in the
HandlerCaseclass as a static method. - Unit tests done.
- Implemented in the
- Handler class
- Restarts
- Restart class
- Implemented in the
Restartclass. - Unit tests done.
- Implemented in the
-
restart-bind- Implemented in the
RestartBindclass. - Unit tests done.
- Implemented in the
-
restart-case- Implemented in the
RestartCaseclass. - Unit tests done.
- Implemented in the
-
with-simple-restart- Implemented in the
RestartCaseclass as a static method. - Unit tests done.
- Implemented in the
- Restart class
- Debugger
- Debugger interface
- Defined in the
Debuggerclass.
- Defined in the
- Throwing debugger
- Implemented in the
ThrowingDebuggerclass. - Tested along with
Errorclass.
- Implemented in the
- Debugger interface
-
*debugger-hook* -
break -
*break-on-signals* - Interactive debugger
- JShell as debugger REPL
-
unwind-protect- Java hasfinallythat is fully equivalent.