IGJoshua / farolero

Thread-safe Common Lisp style conditions and restarts for Clojure(Script) and Babashka.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Do examples return expected result?

fonghou opened this issue · comments

commented

Hi, nice library!

I'm not sure I understand the result from examples in README. Would you mind explain a bit more?

  1. I would expect this returns ::result, but got nil instead.
(handler-bind [::some-condition (fn [condition]
                                  (invoke-restart ::some-restart))]
  (restart-bind [::some-restart (fn [] ::result)]
    (signal ::some-condition)))
;; nil
  1. Should this return ::hello? I got nil again here.
(derive ::some-condition ::parent-condition)

(handler-bind [::some-condition (fn [condition] nil)
               ::parent-condition (fn [condition] (invoke-restart ::some-restart))]
  (restart-bind [::some-restart (fn [] ::hello)]
    (signal ::some-condition)))
;; nil
  1. Why would (print "never reached!) never reached? I would expect it does print "never reached!" line because it's a successful restart.
(restart-case (do (invoke-restart ::some-restart)
                  (println "never reached!"))
  (::some-restart []
    (println "reached!")
    ::return-result))
;; => ::return-result

Thanks!

Hey, thanks for showing interest!

Yes, these are the expected results, and I'll explain why in brief shortly. All the interactions here are explained in detail in the docstrings of the functions and macros.

For the first and second examples, this is because of the use of the -bind variants of the two macros. When a handler is invoked by signal and returns normally, signal will look further up the stack to find more handlers to run until one performs a non-local exit, and if all return normally, it returns nil. The -bind variants of the macros don't introduce any non-local exits on their own, so throw is the only way to exit without searching for more handlers.

Example three uses the restart-case variant though, which introduces a non-local exit. When invoke-restart is called the expression immediately performs a non-local exit to outside the expression and then runs the restart code, returning its return value.

All these behaviors are described in the Common Lisp spec, and I'll admit right now the project readme is geared towards common lispers using Clojure. I'm planning on making the readme give more and better examples in futute to motivate conditions and restarts to Clojure devs.