Created
September 30, 2016 02:09
-
-
Save xiongtx/0fa011f880a68e8bd5b035ef1e1a171d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Debugger == interactive restarter | |
;; If we try to open a non-existent file, we are put into the debugger | |
(with-open-file (in "nonexistent-file.txt") | |
(format t "~A~%" (read-line in nil))) | |
;; The debugger offer a restart that retries the evaluation | |
(with-open-file (str "nonexistent-file.txt" | |
:direction :output) | |
(format str "This file now exists.")) | |
(delete-file "nonexistent-file.txt") | |
;; Custom restarts | |
;; We can define our own restarts | |
(with-simple-restart (foo "Restart with foo.") | |
(error "How should we restart?")) | |
;; More generally, we can use `restart-case' | |
(defun my-symbol-value (name) | |
(if (boundp name) | |
(symbol-value name) | |
(restart-case (error 'unbound-variable :name name) | |
(use-value (value) | |
:report "Specify a value to use." | |
:interactive (lambda () | |
(format t "~&Value to use: ") | |
(list (eval (read)))) | |
value) | |
(store-value (value) | |
:report "Specify a value to use and store." | |
:interactive (lambda () | |
(format t "~&Value to use and store: ") | |
(list (eval (read)))) | |
(setf (symbol-value name) value) | |
value)))) | |
;; Call (my-symbol-value 'undefined-symbol) in the REPL | |
;; Programmatic restarts | |
;; Let's try to programmatically restart based on condition type | |
(handler-case (+ (my-symbol-value 'undefined-symbol) | |
(my-symbol-value 'pi)) | |
(unbound-variable (c) | |
(let ((restart (find-restart 'use-value c))) | |
(when restart | |
(invoke-restart restart 17))))) | |
;; This does not work! | |
;; Let's try another way | |
(handler-bind ((unbound-variable | |
(lambda (c) | |
(let ((restart (find-restart 'use-value c))) | |
(when restart | |
(invoke-restart restart 17)))))) | |
(+ (my-symbol-value 'undefined-symbol) | |
(my-symbol-value 'pi))) | |
;; `handler-case' unwinds the stack | |
;; `handler-bind' does not unwind stack | |
;; Let's look at some macro expansions! | |
(ignore-errors (error "An error")) | |
(with-simple-restart (foo "Simple restart") | |
(error "An error")) | |
(handler-case (error "An error") | |
(error (c) | |
(declare (ignore c)) | |
"Handled error")) | |
;; Resources | |
;; Practical Common Lisp (Peter Seibel) | |
;; http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html | |
;; Common Lisp the Language, 2nd Ed. | |
;; https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node312.html#SECTION003300000000000000000 | |
;; Clojure versions of CL condition system | |
;; Talk by Chris Houser: | |
;; https://www.youtube.com/watch?v=zp0OEDcAro0 | |
;; Write-up of talk: | |
;; https://gist.github.com/msgodf/6f4e43c112b8e89eee3d | |
;; Hugo Duncan's Swell (uses Slingshot) | |
;; https://github.com/hugoduncan/swell | |
;; https://github.com/scgilardi/slingshot |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment