From b4fe711abb1129861b430a2f45ca07b9e29facc6 Mon Sep 17 00:00:00 2001 From: efim Date: Thu, 11 Aug 2022 12:36:22 +0000 Subject: [PATCH] koans with signals, errors and stuff this is a bit complicated, espeially with different objects representing conditions and how hard it is to check inner parts of expressions --- lisp-koans/koans/condition-handlers.lisp | 41 +++++++++++++++--------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lisp-koans/koans/condition-handlers.lisp b/lisp-koans/koans/condition-handlers.lisp index 3a379a6..1bb88a4 100644 --- a/lisp-koans/koans/condition-handlers.lisp +++ b/lisp-koans/koans/condition-handlers.lisp @@ -101,7 +101,7 @@ (very-silly-condition #'handle-very-silly-condition) (most-silly-condition #'handle-most-silly-condition)) (signal (make-condition 'most-silly-condition))) - (assert-equal ____ *list*))) + (assert-equal '(:most-silly-condition :very-silly-condition :silly-condition) *list*))) (define-test multiple-handler-binds ;; It is possible to bind handlers in steps. @@ -110,7 +110,7 @@ (most-silly-condition #'handle-most-silly-condition)) (handler-bind ((very-silly-condition #'handle-very-silly-condition)) (signal (make-condition 'most-silly-condition)))) - (assert-equal ____ *list*))) + (assert-equal '(:most-silly-condition :silly-condition :very-silly-condition) *list*))) (define-test same-handler ;; The same handler may be bound multiple times. @@ -121,7 +121,7 @@ (silly-condition #'handle-silly-condition) (very-silly-condition #'handle-very-silly-condition)) (signal (make-condition 'most-silly-condition)))) - (assert-equal ____ *list*))) + (assert-equal '(:silly-condition :silly-condition :very-silly-condition :silly-condition :very-silly-condition ) *list*))) (define-test handler-types ;; A handler is not executed if it does not match the condition type. @@ -130,7 +130,7 @@ (very-silly-condition #'handle-very-silly-condition) (most-silly-condition #'handle-most-silly-condition)) (signal (make-condition 'very-silly-condition))) - (assert-equal ____ *list*))) + (assert-equal '(:very-silly-condition :silly-condition) *list*))) (define-test handler-transfer-of-control ;; A handler may decline to handle the condition if it returns normally, @@ -143,7 +143,7 @@ (return-from my-block))) (silly-condition #'handle-silly-condition)) (signal (make-condition 'silly-condition)))) - (assert-equal ____ *list*))) + (assert-equal '(:silly-condition) *list*))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -163,7 +163,7 @@ (handler-case (signal (make-condition 'my-error)) (error (condition) (handle-error condition)) (my-error (condition) (handle-my-error condition))) - (assert-equal ____ *list*))) + (assert-equal '(:error) *list*))) ; well, I don't really understand that (define-test handler-case-order ;; The order of handler cases matters. @@ -171,7 +171,7 @@ (handler-case (signal (make-condition 'my-error)) (my-error (condition) (handle-my-error condition)) (error (condition) (handle-error condition))) - (assert-equal ____ *list*))) + (assert-equal '(:my-error) *list*))) (define-test handler-case-type ;; A handler cases is not executed if it does not match the condition type. @@ -179,7 +179,16 @@ (handler-case (signal (make-condition 'error)) (my-error (condition) (handle-my-error condition)) (error (condition) (handle-error condition))) - (assert-equal ____ *list*))) + (assert-equal '(:error) *list*))) + +;;; it seems that difference between #'handler-case and #'handler-bind +;; is that first is like try-catch, where single, first condition for signal is executed +;; (and expressions are not handlers, but things to evaluate) +;; and handler-bind executes all handlers applicable? +;; here handlers are functions +;; http://www.lispworks.com/documentation/HyperSpec/Body/09_ada.htm +;; here it seems that handler can either transfer control - by return-from of return +;; and that "handles" the signal, or "decline" by returning, that that means that following handlers get called ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -199,27 +208,27 @@ (handler-case (divide numerator denominator) (division-by-zero () :division-by-zero) (type-error () :type-error)))) - (assert-equal ____ (try-to-divide 6 2)) - (assert-equal ____ (try-to-divide 6 0)) - (assert-equal ____ (try-to-divide 6 :zero)))) + (assert-equal 3 (try-to-divide 6 2)) + (assert-equal :division-by-zero (try-to-divide 6 0)) + (assert-equal :type-error (try-to-divide 6 :zero)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Condition objects can contain metadata about the specific situation that ;;; occurred in the code. - (define-test accessors-division-by-zero - (let ((condition (handler-case (divide 6 0) (division-by-zero (c) c)))) + (setq my-cond (handler-case (divide 6 0) (division-by-zero (c) c))) + (let ((my-cond (handler-case (divide 6 0) (division-by-zero (c) c)))) ;; Disabled on CLISP and ABCL due to conformance bugs. ;; See https://gitlab.com/gnu-clisp/clisp/-/issues/22 ;; See https://github.com/armedbear/abcl/issues/177 #-(or clisp abcl) - (assert-equal ____ (arithmetic-error-operands condition)) - (let ((operation (arithmetic-error-operation condition))) + (assert-equal '(6 0) (arithmetic-error-operands my-cond)) ; returns '(6 0) + (let ((operation (arithmetic-error-operation my-cond))) ; returns #'/ holy cow ;; Disabled on ABCL due to a conformance bug. ;; See https://github.com/armedbear/abcl/issues/177 #-abcl - (assert-equal ____ (funcall operation 12 4))))) + (assert-equal 3 (funcall operation 12 4))))) (define-test accessors-type-error (let ((condition (handler-case (divide 6 :zero) (type-error (c) c))))