learning koans

- refreshed understanding of lexical vs. dynamic binding
  https://gigamonkeys.com/book/variables.html
- was taught CASE as simpler variant of COND
This commit is contained in:
efim 2022-07-24 13:18:22 +00:00
parent 49c00c24ee
commit fd03924c10
7 changed files with 116 additions and 110 deletions

View File

@ -28,38 +28,38 @@
;;; Sometimes, you will be asked to provide values that are equal to something. ;;; Sometimes, you will be asked to provide values that are equal to something.
(define-test fill-in-the-blanks (define-test fill-in-the-blanks
(assert-equal ____ 2) (assert-equal 2 2)
(assert-equal ____ 3.14) (assert-equal 3.14 3.14)
(assert-equal ____ "Hello World")) (assert-equal "Hello World" "Hello World"))
;;; Sometimes, you will be asked to say whether something is true or false, ;;; Sometimes, you will be asked to say whether something is true or false,
;;; In Common Lisp, the canonical values for truth and falsehood are T and NIL. ;;; In Common Lisp, the canonical values for truth and falsehood are T and NIL.
(define-test assert-true (define-test assert-true
(assert-true ____)) (assert-true t))
(define-test assert-false (define-test assert-false
(assert-false ____)) (assert-false nil))
;; could use C-x C-e (sly-eval-last-expression) to eval just (= 34 34) to check whether T or NIL returns
(define-test true-or-false (define-test true-or-false
(true-or-false? ____ (= 34 34)) (true-or-false? t (= 34 34))
(true-or-false? ____ (= 19 78))) (true-or-false? nil (= 19 78)))
;;; Since T and NIL are symbols, you can type them in lowercase or uppercase; ;;; Since T and NIL are symbols, you can type them in lowercase or uppercase;
;;; by default, Common Lisp will automatically upcase them upon reading. ;;; by default, Common Lisp will automatically upcase them upon reading.
(define-test upcase-downcase (define-test upcase-downcase
;; Try inserting a lowercase t here. ;; Try inserting a lowercase t here.
(assert-equal ____ T) (assert-equal t T)
;; Try inserting an uppercase NIL here. ;; Try inserting an uppercase NIL here.
(assert-equal ____ nil)) (assert-equal NIL nil))
;;; Sometimes, you will be asked to provide a part of an expression that must be ;;; Sometimes, you will be asked to provide a part of an expression that must be
;;; either true or false. ;;; either true or false.
(define-test a-true-assertion (define-test a-true-assertion
(assert-true (= ____ (+ 2 2)))) (assert-true (= 4 (+ 2 2))))
(define-test a-false-assertion (define-test a-false-assertion
(assert-false (= ____ (+ 2 2)))) (assert-false (= 3 (+ 2 2))))

View File

@ -19,25 +19,25 @@
(define-test list-or-atom (define-test list-or-atom
;; The function LISTP will return true if the input is a list. ;; The function LISTP will return true if the input is a list.
;; The function ATOM will return true if the input is an atom. ;; The function ATOM will return true if the input is an atom.
(true-or-false? ____ (listp '(1 2 3))) (true-or-false? t (listp '(1 2 3)))
(true-or-false? ____ (atom '(1 2 3))) (true-or-false? nil (atom '(1 2 3)))
(true-or-false? ____ (listp '("heres" "some" "strings"))) (true-or-false? t (listp '("heres" "some" "strings")))
(true-or-false? ____ (atom '("heres" "some" "strings"))) (true-or-false? nil (atom '("heres" "some" "strings")))
(true-or-false? ____ (listp "a string")) (true-or-false? nil (listp "a string"))
(true-or-false? ____ (atom "a string")) (true-or-false? t (atom "a string"))
(true-or-false? ____ (listp 2)) (true-or-false? nil (listp 2))
(true-or-false? ____ (atom 2)) (true-or-false? t (atom 2))
(true-or-false? ____ (listp '(("first" "list") ("second" "list")))) (true-or-false? t (listp '(("first" "list") ("second" "list"))))
(true-or-false? ____ (atom '(("first" "list") ("second" "list"))))) (true-or-false? nil (atom '(("first" "list") ("second" "list")))))
(define-test the-duality-of-nil (define-test the-duality-of-nil
;; The empty list, NIL, is unique in that it is both a list and an atom. ;; The empty list, NIL, is unique in that it is both a list and an atom.
(true-or-false? ____ (listp nil)) (true-or-false? t (listp nil))
(true-or-false? ____ (atom nil))) (true-or-false? t (atom nil)))
(define-test keywords (define-test keywords
;; Symbols like :HELLO or :LIKE-THIS are keywords. They are treated ;; Symbols like :HELLO or :LIKE-THIS are keywords. They are treated
;; differently in Lisp: they are constants that always evaluate to themselves. ;; differently in Lisp: they are constants that always evaluate to themselves.
(true-or-false? ____ (equal :this-is-a-keyword :this-is-a-keyword)) (true-or-false? t (equal :this-is-a-keyword :this-is-a-keyword))
(true-or-false? ____ (equal :this-is-a-keyword ':this-is-a-keyword)) (true-or-false? t (equal :this-is-a-keyword ':this-is-a-keyword))
(true-or-false? ____ (equal :this-is-a-keyword :this-is-also-a-keyword))) (true-or-false? nil (equal :this-is-a-keyword :this-is-also-a-keyword)))

View File

@ -22,43 +22,49 @@
(c (copy-seq "I am Tom."))) (c (copy-seq "I am Tom.")))
;; A place may be a variable. ;; A place may be a variable.
(setf a 1000) (setf a 1000)
(assert-equal ____ a) (assert-equal 1000 a)
;; A place may be a part of some list. ;; A place may be a part of some list.
(setf (first b) 10) (setf (first b) 10)
(assert-equal ____ b) (assert-equal '(10 20 30 40 50) b)
;; A place may be a character in a string. ;; A place may be a character in a string.
;; The #\x syntax denotes a single character, 'x'. ;; The #\x syntax denotes a single character, 'x'.
(setf (char c 5) #\B (setf (char c 5) #\B
(char c 7) #\b) (char c 7) #\b)
(assert-equal ____ c) (assert-equal "I am Bob." c)
;; There are other kinds of places that we will explore in the future. ;; There are other kinds of places that we will explore in the future.
)) ))
;;; looks like COND is much stronger
;; while CASE only tests with some kind of equasion?
;; with destructuringom as well?
;; http://www.lispworks.com/documentation/HyperSpec/Body/m_case_.htm
;; nope, not desctructuring, but can have check on belonging to a set
;; http://www.lispworks.com/documentation/HyperSpec/Body/m_cond.htm
(define-test case (define-test case
;; CASE is a simple pattern-matching macro, not unlike C's "switch". ;; CASE is a simple pattern-matching macro, not unlike C's "switch".
;; It compares an input against a set of values and evaluates the code for ;; It compares an input against a set of values and evaluates the code for
;; the branch where a match is found. ;; the branch where a match is found.
(let* ((a 4) (let* ((a 4)
(b (case a (b (case a ; and the book have tought COND
(3 :three) (3 :three)
(4 :four) (4 :four)
(5 :five)))) (5 :five))))
(assert-equal ____ b)) (assert-equal :four b))
;; CASE can accept a group of keys. ;; CASE can accept a group of keys.
(let* ((c 4) (let* ((c 4)
(d (case c (d (case c
((0 2 4 6 8) :even-digit) ((0 2 4 6 8) :even-digit)
((1 3 5 7 9) :odd-digit)))) ((1 3 5 7 9) :odd-digit))))
(assert-equal ____ d))) (assert-equal :even-digit d)))
(defun match-special-cases (thing) (defun match-special-cases (thing)
;; T or OTHERWISE passed as the key matches any value. ;; T or OTHERWISE passed as the key matches any value.
;; NIL passed as the key matches no values. ;; NIL passed as the key matches no values.
;; These symbols need to passed in parentheses. ;; These symbols need to passed in parentheses.
(case thing (case thing
(____ :found-a-t) ((t) :found-a-t)
(____ :found-a-nil) ((nil) :found-a-nil)
(____ :something-else))) (otherwise :something-else)))
(define-test special-cases-of-case (define-test special-cases-of-case
;; You need to fill in the blanks in MATCH-SPECIAL-CASES. ;; You need to fill in the blanks in MATCH-SPECIAL-CASES.
@ -71,9 +77,9 @@
(flet ((cartoon-dads (input) (flet ((cartoon-dads (input)
(case input (case input
;; Fill in the blanks with proper cases. ;; Fill in the blanks with proper cases.
____ ((:bart :lisa) :homer)
____ (:stewie :peter)
____ (:stan :randy)
(:this-one-doesnt-happen :fancy-cat) (:this-one-doesnt-happen :fancy-cat)
(t :unknown)))) (t :unknown))))
(assert-equal (cartoon-dads :bart) :homer) (assert-equal (cartoon-dads :bart) :homer)
@ -91,14 +97,14 @@
(string-copy (copy-seq string))) (string-copy (copy-seq string)))
;; The above means that two distinct strings will not be the same under EQL, ;; The above means that two distinct strings will not be the same under EQL,
;; even if they have the same contents. ;; even if they have the same contents.
(true-or-false? ____ (eql string string-copy)) (true-or-false? nil (eql string string-copy))
(true-or-false? ____ (equal string string-copy)) (true-or-false? t (equal string string-copy))
;; The above also means that CASE might give surprising results when used on ;; The above also means that CASE might give surprising results when used on
;; strings. ;; strings.
(let ((match (case string (let ((match (case string
("A string" :matched) ("A string" :matched)
(t :not-matched)))) (t :not-matched))))
(assert-equal ____ match)) (assert-equal :not-matched match))
;; We will explore this topic further in the EQUALITY-DISTINCTIONS lesson. ;; We will explore this topic further in the EQUALITY-DISTINCTIONS lesson.
)) ))
@ -109,4 +115,4 @@
(result (cond ((> number 0) :positive) (result (cond ((> number 0) :positive)
((< number 0) :negative) ((< number 0) :negative)
(t :zero)))) (t :zero))))
(assert-equal ____ result))) (assert-equal :positive result)))

View File

@ -19,30 +19,30 @@
(define-test function-names (define-test function-names
;; In these examples, +, -, *, and / are function names. ;; In these examples, +, -, *, and / are function names.
(assert-equal ____ (+ 2 3)) (assert-equal 5 (+ 2 3))
(assert-equal ____ (- 1 3)) (assert-equal -2 (- 1 3))
(assert-equal ____ (* 7 4)) (assert-equal 28 (* 7 4))
(assert-equal ____ (/ 100 4))) (assert-equal 25 (/ 100 4)))
(define-test numberp (define-test numberp
;; NUMBERP is a predicate which returns true if its argument is a number. ;; NUMBERP is a predicate which returns true if its argument is a number.
(assert-equal ____ (numberp 5)) (assert-equal t (numberp 5))
(assert-equal ____ (numberp 2.0)) (assert-equal t (numberp 2.0))
(assert-equal ____ (numberp "five"))) (assert-equal nil (numberp "five")))
(define-test evaluation-order (define-test evaluation-order
;; Arguments to a function are evaluated before the function is called. ;; Arguments to a function are evaluated before the function is called.
(assert-equal ____ (* (+ 1 2) (- 13 10)))) (assert-equal 9 (* (+ 1 2) (- 13 10))))
(define-test basic-comparisons (define-test basic-comparisons
;; The below functions are boolean functions (predicates) that operate on ;; The below functions are boolean functions (predicates) that operate on
;; numbers. ;; numbers.
(assert-equal ____ (> 25 4)) (assert-equal t (> 25 4))
(assert-equal ____ (< 8 2)) (assert-equal nil (< 8 2))
(assert-equal ____ (= 3 3)) (assert-equal t (= 3 3))
(assert-equal ____ (<= 6 (/ 12 2))) (assert-equal t (<= 6 (/ 12 2)))
(assert-equal ____ (>= 20 (+ 1 2 3 4 5))) (assert-equal t (>= 20 (+ 1 2 3 4 5)))
(assert-equal ____ (/= 15 (+ 4 10)))) (assert-equal t (/= 15 (+ 4 10))))
(define-test quote (define-test quote
;; Preceding a list with a quote (') will tell Lisp not to evaluate a list. ;; Preceding a list with a quote (') will tell Lisp not to evaluate a list.
@ -50,17 +50,17 @@
;; the literal list. ;; the literal list.
;; Evaluating the form (+ 1 2) returns the number 3, but evaluating the form ;; Evaluating the form (+ 1 2) returns the number 3, but evaluating the form
;; '(+ 1 2) returns the list (+ 1 2). ;; '(+ 1 2) returns the list (+ 1 2).
(assert-equal ____ (+ 1 2)) (assert-equal 3 (+ 1 2))
(assert-equal ____ '(+ 1 2)) (assert-equal '(+ 1 2) '(+ 1 2))
(assert-equal ____ (list '+ 1 2)) (assert-equal '(+ 1 2) (list '+ 1 2))
;; The 'X syntax is syntactic sugar for (QUOTE X). ;; The 'X syntax is syntactic sugar for (QUOTE X).
(true-or-false? ____ (equal '(/ 4 0) (quote (/ 4 0))))) (true-or-false? t (equal '(/ 4 0) (quote (/ 4 0)))))
(define-test listp (define-test listp
;; LISTP is a predicate which returns true if the argument is a list. ;; LISTP is a predicate which returns true if the argument is a list.
(assert-equal ____ (listp '(1 2 3))) (assert-equal t (listp '(1 2 3)))
(assert-equal ____ (listp 100)) (assert-equal nil (listp 100))
(assert-equal ____ (listp "Hello world")) (assert-equal nil (listp "Hello world"))
(assert-equal ____ (listp nil)) (assert-equal t (listp nil))
(assert-equal ____ (listp (+ 1 2))) (assert-equal nil (listp (+ 1 2)))
(assert-equal ____ (listp '(+ 1 2)))) (assert-equal t (listp '(+ 1 2))))

View File

@ -17,14 +17,14 @@
;; created: a symbol that names a variable becomes bound to a value. ;; created: a symbol that names a variable becomes bound to a value.
(let ((x 10) (let ((x 10)
(y 20)) (y 20))
(assert-equal ____ (+ x y)) (assert-equal 30 (+ x y))
;; It is possible to shadow previously visible bindings. ;; It is possible to shadow previously visible bindings.
(let ((y 30)) (let ((y 30))
(assert-equal ____ (+ x y))) (assert-equal 40 (+ x y)))
(assert-equal ____ (+ x y))) (assert-equal 30 (+ x y)))
;; Variables bound by LET have a default value of NIL. ;; Variables bound by LET have a default value of NIL.
(let (x) (let (x)
(assert-equal ____ x))) (assert-equal nil x)))
(define-test let-versus-let* (define-test let-versus-let*
;; LET* is similar to LET, except the bindings are established sequentially, ;; LET* is similar to LET, except the bindings are established sequentially,
@ -33,30 +33,30 @@
(y 20)) (y 20))
(let ((x (+ y 100)) (let ((x (+ y 100))
(y (+ x 100))) (y (+ x 100)))
(assert-equal ____ x) (assert-equal 120 x)
(assert-equal ____ y)) (assert-equal 110 y))
(let* ((x (+ y 100)) (let* ((x (+ y 100))
(y (+ x 100))) (y (+ x 100)))
;; Which X is used to compute the value of Y? ;; Which X is used to compute the value of Y?
(assert-equal ____ x) (assert-equal 120 x)
(assert-equal ____ y)))) (assert-equal 220 y))))
(define-test let-it-be-equal (define-test let-it-be-equal
;; Fill in the LET and LET* to get the tests to pass. ;; Fill in the LET and LET* to get the tests to pass.
(let ((a 1) (let ((a 1)
(b :two) (b :two)
(c "Three")) (c "Three"))
(let ((____ ____) (let ((a 100)
(____ ____) (b (* 200 a))
(____ ____)) (c "Jellyfish"))
(assert-equal a 100) (assert-equal a 100)
(assert-equal b 200) (assert-equal b 200)
(assert-equal c "Jellyfish")) (assert-equal c "Jellyfish"))
(let* ((____ ____) (let* ((a 121)
(____ ____) (b (+ a 79))
;; In this third binding, you are allowed to use the variables bound ;; In this third binding, you are allowed to use the variables bound
;; by the previous two LET* bindings. ;; by the previous two LET* bindings.
(____ ____)) (c (+ a (/ b a))))
(assert-equal a 121) (assert-equal a 121)
(assert-equal b 200) (assert-equal b 200)
(assert-equal c (+ a (/ b a)))))) (assert-equal c (+ a (/ b a))))))

View File

@ -14,39 +14,39 @@
(define-test t-and-nil-are-opposites (define-test t-and-nil-are-opposites
;; NOT is a function which returns the boolean opposite of its argument. ;; NOT is a function which returns the boolean opposite of its argument.
(true-or-false? ____ (not nil)) (true-or-false? t (not nil))
(true-or-false? ____ (not t))) (true-or-false? nil (not t)))
(define-test nil-and-empty-list-are-the-same-thing (define-test nil-and-empty-list-are-the-same-thing
;; In Common Lisp, NIL is also the empty list. ;; In Common Lisp, NIL is also the empty list.
(true-or-false? ____ '()) (true-or-false? NIL '())
(true-or-false? ____ (not '()))) (true-or-false? t (not '())))
(define-test in-lisp-many-things-are-true (define-test in-lisp-many-things-are-true
;; In Common Lisp, the canonical values for truth is T. ;; In Common Lisp, the canonical values for truth is T.
;; However, everything that is non-NIL is true, too. ;; However, everything that is non-NIL is true, too.
(true-or-false? ____ 5) (true-or-false? t 5)
(true-or-false? ____ (not 5)) (true-or-false? nil (not 5))
(true-or-false? ____ "a string") (true-or-false? t "a string")
;; Even an empty string... ;; Even an empty string...
(true-or-false? ____ "") (true-or-false? t "")
;; ...or a list containing a NIL... ;; ...or a list containing a NIL...
(true-or-false? ____ (list nil)) (true-or-false? t (list nil))
;; ...or an array with no elements... ;; ...or an array with no elements...
(true-or-false? ____ (make-array 0)) (true-or-false? t (make-array 0))
;; ...or the number zero. ;; ...or the number zero.
(true-or-false? ____ 0)) (true-or-false? t 0))
(define-test and (define-test and
;; The logical operator AND can take multiple arguments. ;; The logical operator AND can take multiple arguments.
(true-or-false? ____ (and t t t t t)) (true-or-false? t (and t t t t t))
(true-or-false? ____ (and t t nil t t)) (true-or-false? nil (and t t nil t t))
;; If all values passed to AND are true, it returns the last value. ;; If all values passed to AND are true, it returns the last value.
(assert-equal ____ (and t t t t t 5))) (assert-equal 5 (and t t t t t 5)))
(define-test or (define-test or
;; The logical operator OR can also take multiple arguments. ;; The logical operator OR can also take multiple arguments.
(true-or-false? ____ (or nil nil nil t nil)) (true-or-false? t (or nil nil nil t nil))
;; OR returns the first non-NIL value it encounters, or NIL if there are none. ;; OR returns the first non-NIL value it encounters, or NIL if there are none.
(assert-equal ____ (or nil nil nil)) (assert-equal nil (or nil nil nil))
(assert-equal ____ (or 1 2 3 4 5))) (assert-equal 1 (or 1 2 3 4 5)))

View File

@ -13,7 +13,7 @@
;;; limitations under the License. ;;; limitations under the License.
(define-test shadowing (define-test shadowing
(assert-equal ____ (let ((z 4)) (list z (let ((z 2)) z))))) (assert-equal '(4 2) (let ((z 4)) (list z (let ((z 2)) z)))))
(defun block-1 () (defun block-1 ()
(block here (block here
@ -28,19 +28,19 @@
(return-from outer 'valve))) (return-from outer 'valve)))
(define-test block-return-from (define-test block-return-from
(assert-equal ____ (block-1)) (assert-equal 4 (block-1))
(assert-equal ____ (block-2))) (assert-equal 'space (block-2)))
;;; See http://www.gigamonkeys.com/book/variables.html ;;; See http://www.gigamonkeys.com/book/variables.html
(define-test lexical-variables-can-be-enclosed (define-test lexical-variables-can-be-enclosed
(assert-equal ____ (let ((f (let ((x 10)) (assert-equal 10 (let ((f (let ((x 10))
(lambda () x)))) (lambda () x))))
(let ((x 20)) (let ((x 20))
(funcall f))))) (funcall f)))))
(define-test dynamic-variables-are-affected-by-execution-path (define-test dynamic-variables-are-affected-by-execution-path
(assert-equal ____ (let ((f (let ((x 10)) (assert-equal 20 (let ((f (let ((x 10))
(declare (special x)) (declare (special x))
(lambda () x)))) (lambda () x))))
(let ((x 20)) (let ((x 20))