buch of things to remind myself
- characters are # and non-excape, #\a - i am way to quick to judge pairwise operations from left with #'reduce - iteration can be actually simple with dotimes, dolist. i'm quite afraid of #'loop but #'do seems cool and inviting
This commit is contained in:
parent
e076e76575
commit
9c64cf128f
|
@ -22,11 +22,12 @@
|
|||
(dolist (number numbers)
|
||||
;; (INCF PLACE N) is equivalent to (SETF PLACE (+ N PLACE)).
|
||||
(incf sum number))
|
||||
(assert-equal ____ sum))
|
||||
(assert-equal 108 sum))
|
||||
;; DOLIST can optionally return a value.
|
||||
(let ((sum 0))
|
||||
(assert-equal ____ (dolist (number numbers sum)
|
||||
(assert-equal 108 (dolist (number numbers sum)
|
||||
(incf sum number))))))
|
||||
;; (apply #'+ '(4 8 15 16 23 42))
|
||||
|
||||
(define-test dotimes
|
||||
;; The macro DOTIMES binds a variable to subsequent integers from 0 to
|
||||
|
@ -34,10 +35,10 @@
|
|||
(let ((stack '()))
|
||||
(dotimes (i 5)
|
||||
(push i stack))
|
||||
(assert-equal ____ stack))
|
||||
(assert-equal '(4 3 2 1 0) stack))
|
||||
;; DOTIMES can optionally return a value.
|
||||
(let ((stack '()))
|
||||
(assert-equal ____ (dotimes (i 5 stack)
|
||||
(assert-equal '(4 3 2 1 0) (dotimes (i 5 stack)
|
||||
(push i stack)))))
|
||||
|
||||
(define-test do
|
||||
|
@ -47,7 +48,7 @@
|
|||
(do ((i 0 (1+ i)))
|
||||
((> i 5))
|
||||
(push i result))
|
||||
(assert-equal ____ result))
|
||||
(assert-equal '(5 4 3 2 1 0) result))
|
||||
;; The epilogue of DO can return a value.
|
||||
(let ((result (do ((i 0 (1+ i))
|
||||
;; A variable bound by DO noes not need to be updated on
|
||||
|
@ -55,7 +56,7 @@
|
|||
(result '()))
|
||||
((> i 5) (nreverse result))
|
||||
(push i result))))
|
||||
(assert-equal ____ result)))
|
||||
(assert-equal '(0 1 2 3 4 5) result)))
|
||||
|
||||
(define-test loop-basic-form
|
||||
;; The macro LOOP in its simple form loops forever. It is possible to stop the
|
||||
|
@ -64,10 +65,10 @@
|
|||
(loop (incf counter)
|
||||
(when (>= counter 100)
|
||||
(return counter)))
|
||||
(assert-equal ____ counter))
|
||||
(assert-equal 100 counter))
|
||||
;; The RETURN special form can return a value out of a LOOP.
|
||||
(let ((counter 0))
|
||||
(assert-equal ____ (loop (incf counter)
|
||||
(assert-equal 100 (loop (incf counter)
|
||||
(when (>= counter 100)
|
||||
(return counter)))))
|
||||
;; The extended form of LOOP will be contemplated in a future koan.
|
||||
|
|
|
@ -19,79 +19,96 @@
|
|||
;; Inside MAPCAR, he function 1+ will be applied to each element of NUMBERS.
|
||||
;; A new list will be collected from the results.
|
||||
(assert-equal '(2 3 4 5 6 7) (mapcar #'1+ numbers))
|
||||
(assert-equal ____ (mapcar #'- numbers))
|
||||
(assert-equal ____ (mapcar #'list numbers))
|
||||
(assert-equal ____ (mapcar #'evenp numbers))
|
||||
(assert-equal ____ (mapcar #'numberp numbers))
|
||||
(assert-equal ____ (mapcar #'stringp numbers))
|
||||
(assert-equal '(-1 -2 -3 -4 -5 -6) (mapcar #'- numbers))
|
||||
(assert-equal '((1) (2) (3) (4) (5) (6)) (mapcar #'list numbers))
|
||||
(assert-equal '(nil t nil t nil t) (mapcar #'evenp numbers))
|
||||
(assert-equal '(t t t t t t) (mapcar #'numberp numbers))
|
||||
(assert-equal '(nil nil nil nil nil nil ) (mapcar #'stringp numbers))
|
||||
;; MAPCAR can work on multiple lists. The function will receive one argument
|
||||
;; from each list.
|
||||
(let ((other-numbers '(4 8 15 16 23 42)))
|
||||
(assert-equal ____ (mapcar #'+ numbers other-numbers))
|
||||
(assert-equal ____ (mapcar #'* numbers other-numbers))
|
||||
(assert-equal '(5 10 18 20 28 48) (mapcar #'+ numbers other-numbers))
|
||||
(assert-equal `(4 16 45 ,(* 16 4) ,(* 23 5) ,(* 42 6) ) (mapcar #'* numbers other-numbers))
|
||||
;; The function MOD performs modulo division.
|
||||
(assert-equal ____ (mapcar #'mod other-numbers numbers)))))
|
||||
(assert-equal `(0 0 0 0 3 0) (mapcar #'mod other-numbers numbers)))))
|
||||
|
||||
(define-test mapcar-lambda
|
||||
;; MAPCAR is often used with anonymous functions.
|
||||
(let ((numbers '(8 21 152 37 403 14 7 -34)))
|
||||
(assert-equal ____ (mapcar (lambda (x) (mod x 10)) numbers)))
|
||||
(assert-equal '(8 1 2 7 3 4 7 6) (mapcar (lambda (x) (mod x 10)) numbers)))
|
||||
(let ((strings '("Mary had a little lamb"
|
||||
"Old McDonald had a farm"
|
||||
"Happy birthday to you")))
|
||||
(assert-equal ____ (mapcar (lambda (x) (subseq x 4 12)) strings))))
|
||||
(assert-equal '(" had a l" "McDonald" "y birthd") (mapcar (lambda (x) (subseq x 4 12)) strings))))
|
||||
|
||||
(define-test map
|
||||
;; MAP is a variant of MAPCAR that works on any sequences.
|
||||
;; It allows to specify the type of the resulting sequence.
|
||||
(let ((string "lorem ipsum"))
|
||||
(assert-equal ____ (map 'string #'char-upcase string))
|
||||
(assert-equal ____ (map 'list #'char-upcase string))
|
||||
(assert-equal "LOREM IPSUM" (map 'string #'char-upcase string))
|
||||
(assert-equal '(#\L #\O #\R #\E #\M #\ #\I #\P #\S #\U #\M) (map 'list #'char-upcase string))
|
||||
;; Not all vectors containing characters are strings.
|
||||
(assert-equalp ____ (map '(vector t) #'char-upcase string))))
|
||||
(assert-equalp #(#\L #\O #\R #\E #\M #\ #\I #\P #\S #\U #\M) (map '(vector t) #'char-upcase string))))
|
||||
;; have no idea what's with the T
|
||||
|
||||
(vector 1 2 3)
|
||||
#(1 2 3 4)
|
||||
|
||||
(define-test transposition
|
||||
;; MAPCAR gives the function as many arguments as there are lists.
|
||||
(flet ((transpose (lists) (apply #'mapcar ____ lists)))
|
||||
(let ((list '((1 2 3)
|
||||
(4 5 6)
|
||||
(7 8 9)))
|
||||
(transposed-list '((1 4 7)
|
||||
(2 5 8)
|
||||
(3 6 9))))
|
||||
(assert-equal transposed-list (transpose list))
|
||||
(assert-equal ____ (transpose (transpose list))))
|
||||
(assert-equal ____ (transpose '(("these" "making")
|
||||
("pretzels" "me")
|
||||
("are" "thirsty"))))))
|
||||
;; MAPCAR gives the function as many arguments as there are lists.
|
||||
(flet ((transpose (lists) (apply #'mapcar #'list lists)))
|
||||
(let ((list '((1 2 3)
|
||||
(4 5 6)
|
||||
(7 8 9)))
|
||||
(transposed-list '((1 4 7)
|
||||
(2 5 8)
|
||||
(3 6 9))))
|
||||
(assert-equal transposed-list (transpose list))
|
||||
(assert-equal list (transpose (transpose list))))
|
||||
(assert-equal '(("these" "pretzels" "are")
|
||||
("making" "me" "thirsty")) (transpose '(("these" "making")
|
||||
("pretzels" "me")
|
||||
("are" "thirsty"))))))
|
||||
|
||||
(mapcar #'list (mapcar #'list '(1 2 3) '(11 22 33) '(111 222 333)))
|
||||
;; welp, that wraps result in list
|
||||
(defun my-transpose (&rest lists)
|
||||
(apply #'mapcar #'list lists))
|
||||
(my-transpose (my-transpose '(1 2 3) '(11 22 33) '(111 222 333)))
|
||||
|
||||
(defun my-transpose2 (lists)
|
||||
(apply #'mapcar #'list lists))
|
||||
(my-transpose2 (my-transpose2 '((1 2 3) (11 22 33) (111 222 333))))
|
||||
|
||||
(define-test reduce
|
||||
;; The function REDUCE combines the elements of a list by applying a binary
|
||||
;; function to the elements of a sequence from left to right.
|
||||
(assert-equal 15 (reduce #'+ '(1 2 3 4 5)))
|
||||
(assert-equal ____ (reduce #'+ '(1 2 3 4)))
|
||||
(assert-equal ____ (reduce #'expt '(1 2 3 4 5))))
|
||||
;; The function REDUCE combines the elements of a list by applying a binary
|
||||
;; function to the elements of a sequence from left to right.
|
||||
(assert-equal 15 (reduce #'+ '(1 2 3 4 5)))
|
||||
(assert-equal 10 (reduce #'+ '(1 2 3 4)))
|
||||
(assert-equal 1 (reduce #'expt '(1 2 3 4 5))))
|
||||
|
||||
(reduce #'expt '(1 2 3))
|
||||
|
||||
(define-test reduce-from-end
|
||||
;; The :FROM-END keyword argument can be used to reduce from right to left.
|
||||
(let ((numbers '(1 2 3 4 5)))
|
||||
(assert-equal ____ (reduce #'cons numbers))
|
||||
(assert-equal ____ (reduce #'cons numbers :from-end t)))
|
||||
;; The :FROM-END keyword argument can be used to reduce from right to left.
|
||||
(let ((numbers '(1 2 3 4 5)))
|
||||
(assert-equal '((((1 . 2) . 3) . 4) . 5) (reduce #'cons numbers)) ; and this I failed at first try
|
||||
(assert-equal '(1 . (2 . (3 . (4 . 5)))) (reduce #'cons numbers :from-end t)))
|
||||
(let ((numbers '(2 3 2)))
|
||||
(assert-equal ____ (reduce #'expt numbers))
|
||||
(assert-equal ____ (reduce #'expt numbers :from-end t))))
|
||||
(assert-equal (expt (expt 2 3) 2) (reduce #'expt numbers))
|
||||
(assert-equal (expt 2 9) (reduce #'expt numbers :from-end t)))) ; this I failed at first try
|
||||
|
||||
(define-test reduce-initial-value
|
||||
;; :INITIAL-VALUE can supply the initial value for the reduction.
|
||||
(let ((numbers '(1 2 3 4 5)))
|
||||
(assert-equal ____ (reduce #'* numbers))
|
||||
(assert-equal ____ (reduce #'* numbers :initial-value 0))
|
||||
(assert-equal ____ (reduce #'* numbers :initial-value -1))))
|
||||
(assert-equal 120 (reduce #'* numbers))
|
||||
(assert-equal 0 (reduce #'* numbers :initial-value 0))
|
||||
(assert-equal -120 (reduce #'* numbers :initial-value -1))))
|
||||
|
||||
(define-test inner-product
|
||||
;; MAPCAR and REDUCE are powerful when used together.
|
||||
;; Fill in the blanks to produce a local function that computes an inner
|
||||
;; product of two vectors.
|
||||
(flet ((inner-product (x y) (reduce ____ (mapcar ____ x y))))
|
||||
(flet ((inner-product (x y) (reduce #'+ (mapcar #'* x y))))
|
||||
(assert-equal 32 (inner-product '(1 2 3) '(4 5 6)))
|
||||
(assert-equal 310 (inner-product '(10 20 30) '(4 3 7)))))
|
||||
|
|
|
@ -14,60 +14,64 @@
|
|||
|
||||
(define-test what-is-a-string
|
||||
(let ((string "Do, or do not. There is no try."))
|
||||
(true-or-false? ____ (typep string 'string))
|
||||
(true-or-false? t (typep string 'string))
|
||||
;; Strings are vectors of characters.
|
||||
(true-or-false? ____ (typep string 'array))
|
||||
(true-or-false? ____ (typep string 'vector))
|
||||
(true-or-false? ____ (typep string '(vector character)))
|
||||
(true-or-false? ____ (typep string 'integer))))
|
||||
(true-or-false? t (typep string 'array))
|
||||
(true-or-false? t (typep string 'vector))
|
||||
(true-or-false? t (typep string '(vector character)))
|
||||
(true-or-false? nil (typep string 'integer))))
|
||||
|
||||
(define-test multiline-string
|
||||
;; A Lisp string can span multiple lines.
|
||||
(let ((string "this is
|
||||
a multi
|
||||
line string"))
|
||||
(true-or-false? ____ (typep string 'string))))
|
||||
(true-or-false? t (typep string 'string))))
|
||||
|
||||
(define-test escapes-in-strings
|
||||
;; Quotes and backslashes in Lisp strings must be escaped.
|
||||
(let ((my-string "this string has one of these \" and a \\ in it"))
|
||||
(true-or-false? ____ (typep my-string 'string))))
|
||||
(true-or-false? t (typep my-string 'string))))
|
||||
|
||||
(let ((my-string "this string has one of these \" and a \\ in it"))
|
||||
(format t "~&unsescaped string ~S" my-string)
|
||||
(format t "~&escaped string ~A" my-string)) ; yay, that's how I remember it from the book
|
||||
;; printing escaped characters for pretty text output
|
||||
|
||||
(define-test substrings
|
||||
;; Since strings are sequences, it is possible to use SUBSEQ on them.
|
||||
(let ((string "Lorem ipsum dolor sit amet"))
|
||||
(assert-equal ____ (subseq string 12))
|
||||
(assert-equal ____ (subseq string 6 11))
|
||||
(assert-equal ____ (subseq string 1 5))))
|
||||
;; Since strings are sequences, it is possible to use SUBSEQ on them.
|
||||
(let ((string "Lorem ipsum dolor sit amet"))
|
||||
(assert-equal "dolor sit amet" (subseq string 12))
|
||||
(assert-equal "ipsum" (subseq string 6 11))
|
||||
(assert-equal "orem" (subseq string 1 5))))
|
||||
|
||||
(define-test strings-versus-characters
|
||||
;; Strings and characters have distinct types.
|
||||
(true-or-false? ____ (typep #\a 'character))
|
||||
(true-or-false? ____ (typep "A" 'character))
|
||||
(true-or-false? ____ (typep #\a 'string))
|
||||
(true-or-false? t (typep #\a 'character))
|
||||
(true-or-false? nil (typep "A" 'character))
|
||||
(true-or-false? nil (typep #\a 'string))
|
||||
;; One can use both AREF and CHAR to refer to characters in a string.
|
||||
(let ((my-string "Cookie Monster"))
|
||||
(assert-equal ____ (char my-string 0))
|
||||
(assert-equal ____ (char my-string 3))
|
||||
(assert-equal ____ (aref my-string 7))))
|
||||
(assert-equal #\C (char my-string 0))
|
||||
(assert-equal #\k (char my-string 3))
|
||||
(assert-equal #\M (aref my-string 7))))
|
||||
|
||||
(define-test concatenating-strings
|
||||
;; Concatenating strings in Common Lisp is possible, if a little cumbersome.
|
||||
(let ((a "Lorem")
|
||||
(b "ipsum")
|
||||
(c "dolor"))
|
||||
(assert-equal ____ (concatenate 'string a " " b " " c))))
|
||||
(assert-equal "Lorem ipsum dolor" (concatenate 'string a " " b " " c))))
|
||||
|
||||
(define-test searching-for-characters
|
||||
;; The function POSITION can be used to find the first position of an element
|
||||
;; in a sequence. If the element is not found, NIL is returned.
|
||||
(assert-equal ____ (position #\b "abc"))
|
||||
(assert-equal ____ (position #\c "abc"))
|
||||
(assert-equal ____ (position #\d "abc")))
|
||||
(assert-equal 1 (position #\b "abc"))
|
||||
(assert-equal 2 (position #\c "abc"))
|
||||
(assert-equal nil (position #\d "abc")))
|
||||
|
||||
(define-test finding-substrings
|
||||
;; The function SEARCH can be used to search a sequence for subsequences.
|
||||
(let ((title "A supposedly fun thing I'll never do again"))
|
||||
(assert-equal ____ (search "supposedly" title))
|
||||
(assert-equal 12 (search ____ title))))
|
||||
|
||||
(assert-equal 2 (search "supposedly" title))
|
||||
(assert-equal 12 (search " fun" title))))
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
(define-test make-struct
|
||||
(let ((player (make-basketball-player :name "Larry" :team :celtics
|
||||
:number 33)))
|
||||
(true-or-false? ____ (basketball-player-p player))
|
||||
(assert-equal ____ (basketball-player-name player))
|
||||
(assert-equal ____ (basketball-player-team player))
|
||||
(assert-equal ____ (basketball-player-number player))
|
||||
(true-or-false? t (basketball-player-p player))
|
||||
(assert-equal "Larry" (basketball-player-name player))
|
||||
(assert-equal :celtics (basketball-player-team player))
|
||||
(assert-equal 33 (basketball-player-number player))
|
||||
(setf (basketball-player-team player) :retired)
|
||||
(assert-equal ____ (basketball-player-team player))))
|
||||
(assert-equal :retired (basketball-player-team player))))
|
||||
|
||||
;;; Structure fields can have default values.
|
||||
|
||||
|
@ -46,8 +46,8 @@
|
|||
(let ((player (make-baseball-player)))
|
||||
;; We have not specified a default value for NAME, therefore we cannot
|
||||
;; read it here - it would invoke undefined behaviour.
|
||||
(assert-equal ____ (baseball-player-team player))
|
||||
(assert-equal ____ (baseball-player-position player))))
|
||||
(assert-equal :red-sox (baseball-player-team player))
|
||||
(assert-equal :outfield (baseball-player-position player))))
|
||||
|
||||
;;; The accessor names can get pretty long. It's possible to specify a different
|
||||
;;; prefix with the :CONC-NAME option.
|
||||
|
@ -58,9 +58,9 @@
|
|||
(define-test struct-access
|
||||
(let ((player (make-american-football-player
|
||||
:name "Drew Brees" :position :qb :team "Saints")))
|
||||
(assert-equal ____ (nfl-guy-name player))
|
||||
(assert-equal ____ (nfl-guy-team player))
|
||||
(assert-equal ____ (nfl-guy-position player))))
|
||||
(assert-equal "Drew Brees" (nfl-guy-name player))
|
||||
(assert-equal "Saints" (nfl-guy-team player))
|
||||
(assert-equal :qb (nfl-guy-position player))))
|
||||
|
||||
;;; Structs can be defined to include other structure definitions.
|
||||
;;; This form of inheritance allows composition of objects.
|
||||
|
@ -73,14 +73,14 @@
|
|||
:start-year 2004 :end-year 2011
|
||||
:name "Kobe Bryant"
|
||||
:team :lakers :number 24)))
|
||||
(assert-equal ____ (nba-contract-start-year contract))
|
||||
(assert-equal ____ (type-of contract))
|
||||
(assert-equal 2004 (nba-contract-start-year contract))
|
||||
(assert-equal 'nba-contract (type-of contract))
|
||||
;; Inherited structures follow the rules of type hierarchy.
|
||||
(true-or-false? ____ (typep contract 'basketball-player))
|
||||
(true-or-false? t (typep contract 'basketball-player))
|
||||
;; One can access structure fields both with the structure's own accessors
|
||||
;; and with the inherited accessors.
|
||||
(assert-equal ____ (nba-contract-team contract))
|
||||
(assert-equal ____ (basketball-player-team contract))))
|
||||
(assert-equal :lakers (nba-contract-team contract))
|
||||
(assert-equal :lakers (basketball-player-team contract))))
|
||||
|
||||
;;; Copying a structure named FOO is handled with the COPY-FOO function.
|
||||
;;; All such copies are shallow.
|
||||
|
@ -91,21 +91,21 @@
|
|||
(manning-2 (make-american-football-player
|
||||
:name "Manning" :team (list "Colts" "Broncos"))))
|
||||
;; MANNING-1 and MANNING-2 are different objects...
|
||||
(true-or-false? ____ (eq manning-1 manning-2))
|
||||
(true-or-false? nil (eq manning-1 manning-2))
|
||||
;;...but they contain the same information.
|
||||
(true-or-false? ____ (equalp manning-1 manning-2))
|
||||
(true-or-false? t (equalp manning-1 manning-2))
|
||||
(let ((manning-3 (copy-american-football-player manning-1)))
|
||||
(true-or-false? ____ (eq manning-1 manning-3))
|
||||
(true-or-false? ____ (equalp manning-1 manning-3))
|
||||
(true-or-false? nil (eq manning-1 manning-3))
|
||||
(true-or-false? t (equalp manning-1 manning-3))
|
||||
;; Setting the slot of one instance does not modify the others...
|
||||
(setf (nfl-guy-name manning-1) "Rogers")
|
||||
(true-or-false? ____ (string= (nfl-guy-name manning-1)
|
||||
(true-or-false? nil (string= (nfl-guy-name manning-1)
|
||||
(nfl-guy-name manning-3)))
|
||||
(assert-equal ____ (nfl-guy-name manning-1))
|
||||
(assert-equal ____ (nfl-guy-name manning-3))
|
||||
(assert-equal "Rogers" (nfl-guy-name manning-1))
|
||||
(assert-equal "Manning" (nfl-guy-name manning-3))
|
||||
;; ...but modifying shared structure may affect other instances.
|
||||
(setf (car (nfl-guy-team manning-1)) "Giants")
|
||||
(true-or-false? ____ (string= (car (nfl-guy-team manning-1))
|
||||
(true-or-false? t (string= (car (nfl-guy-team manning-1))
|
||||
(car (nfl-guy-team manning-3))))
|
||||
(assert-equal ____ (car (nfl-guy-team manning-1)))
|
||||
(assert-equal ____ (car (nfl-guy-team manning-3))))))
|
||||
(assert-equal "Giants" (car (nfl-guy-team manning-1)))
|
||||
(assert-equal "Giants" (car (nfl-guy-team manning-3))))))
|
||||
|
|
Loading…
Reference in New Issue