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

:missing-restart error

fonghou opened this issue · comments

commented

Want to report an issue where :missing-restart should be reported, but didn't.

Below code uses two nested handler-binds. The inner handler invokes ::restart2 that doesn't exist (i.e. typo). It'd nice if (:type :missing-restart :restart-name ::restart2 ...) could be reported (this is what I see when just evaling the inner handler-bind form along). But when evaling outer handler-bind form it gave a mush less helpful error message below.

   (fc/handler-bind [:farolero.core/condition
                     (fn [condition args]
                       (println "In outer handler")
                       (fc/invoke-restart ::restart :a 1 :b 2))]
     (fc/handler-bind [::signal
                       (fn [condition args]
                         (println "In inner handler")
                         (fc/invoke-restart ::restart2 :a 1 :b 2))]
       (restart-case (do (fc/error ::signal {:cause "unknown"})
                         (println "Never reached"))
         (::restart [& args]
           (println "Invoked the restart!")
           (prn args)
           :result))))
In inner handler
Execution error (ArityException) at farolero.core/signal$fn (core.cljc:482).
Wrong number of args (7) passed to: cljdata.explore/eval58548/fn--58549

Hey, thanks for checking out farolero! The problem here is a simple one.

You're invoking your first handler with the condition, and one argument, which works as expected, but when you invoke the missing restart farolero signals a :farolero.core/control-error, which includes keyword arguments. The solution here is to make sure your :farolero.core/condition handler takes rest arguments!

So change the outer handler to rest arguments, and let me know if you run into any other issues!

In order to help with this problem in future, I'll leave this issue open till I get a section in the readme demonstrating additional handler arguments.

commented

Got it. Thanks!

   (fc/handler-bind [:farolero.core/condition
                     (fn [condition & args]
                       (println "In outer handler")
                       (prn condition)
                       (prn args)
                       (fc/invoke-restart ::restart :a 1 :b 2))]
     (fc/handler-bind [::signal
                       (fn [condition & args]
                         (println "In inner handler")
                         (prn condition)
                         (prn args)
                         (fc/invoke-restart ::restart2 :a 1 :b 2))]
       (restart-case (do (fc/error ::signal {:cause "unknown"})
                         (println "Never reached"))
         (::restart [& args]
           (println "Invoked the restart!")
           (prn args)
           :result))))

This output make sense now.

In inner handler
:cljdata.explore/signal
({:cause "unknown"})
In outer handler
:farolero.core/control-error
(:type :missing-restart :restart-name :cljdata.explore/restart2 :available-restarts (#:farolero.core{:restart-fn #function[cljdata.explore/eval60053/fn--60061/fn--60065/fn--60068], :restart-name :cljdata.explore/restart, :restart-thread #object[java.lang.Thread 0x78a3a518 "Thread[nREPL-session-f1a7e898-c1f3-4dca-8b86-d4d37eb73fe9,5,main]"]} #:farolero.core{:restart-name :farolero.core/throw, :restart-reporter "Throw the condition as an exception", :restart-interactive #function[clojure.core/constantly/fn--5690], :restart-fn #function[farolero.core/fn--40632]}))
Invoked the restart!
(:a 1 :b 2)
:result

Alright, I've updated the readme, it should hopefully be a bit more clear.