366 lines
8.9 KiB
Common Lisp
366 lines
8.9 KiB
Common Lisp
(FIRST '(5 2 3))
|
|
(SECOND '(5 2 3))
|
|
(THIRD '(5 2 3))
|
|
(REST '(5 2 3 5 1 6))
|
|
|
|
(cons 1 '( 2 )) ; adds number to the list
|
|
(cons 1 2) ; just a cons element
|
|
(cons 'SINK '(OR SWIM)) ; adds symbol to the list
|
|
(cons 'SINK 'SWIM) ; just a cons element with symbols
|
|
(cons 'start nil) ; list is when last cons ends with `nil
|
|
(cons 'start (cons 'end nil)) ; if we are to construct list from cons cells (and not from print notation)
|
|
(cons 'nil 'nil) ; putting nil into CDR means having list with that item as CAR
|
|
(cons '(PHONE HOME) nil)
|
|
;; even though `nil is same as '() many properties of lists hold only for non-empty lists, i.e
|
|
;; with at least one cons cell
|
|
;; for example main relationship between CAR, CDR & CONS
|
|
(equal
|
|
'(1 2 3 4)
|
|
(cons
|
|
(car '(1 2 3 4))
|
|
(cdr '(1 2 3 4))))
|
|
;; doesn't work for () :
|
|
(equal
|
|
'()
|
|
(cons
|
|
(car '())
|
|
(cdr '())))
|
|
|
|
(cons
|
|
(car '())
|
|
(cdr '())) ; => (NIL)
|
|
|
|
;;; exercises 3
|
|
(defun half (x)
|
|
(/ x 2))
|
|
|
|
(defun cube (x)
|
|
(* x x x))
|
|
|
|
(defun pythag (x y)
|
|
(sqrt (+ (* x x) (* y y))))
|
|
|
|
;; variables /are named by/ symbols, they are *not* symbols
|
|
;; funcitons are /aldo named by/ symbols
|
|
|
|
;;; symbols and lists as data
|
|
;; use ` - tilde to tell lisp interpreter
|
|
;; to treat symbol not as a name for variable (and evaluate to its value)
|
|
;; but to treat it as symbol (data)
|
|
;;
|
|
;; most symbols need to be quoted to be treated as symbols
|
|
;; some exceptions are t and nil which are self evaluating
|
|
|
|
(defun riddle (x y)
|
|
(list `why `is `a x `like `a y))
|
|
(riddle `raven `desk)
|
|
|
|
;;; Evaluation Rule for quoted Quoted Objects:
|
|
;;; quoted object evaluates to the object itself without the quote
|
|
|
|
;; 3 ways of creating lists
|
|
`(foo bar baz) ; everything inside list is not evaluated
|
|
|
|
(list `foo `bar `baz (* 33 33)) ; allows for "computed elements"" "
|
|
(cons `foo `(bar baz))
|
|
|
|
;; 3.11
|
|
(defun longer-than (l1 l2)
|
|
(> (length l1) (length l2)))
|
|
|
|
(defun call-up (caller callee)
|
|
(list `hello callee `this `is caller `calling))
|
|
|
|
(defun crank-call (caller callee)
|
|
`(hello callee this is caller calling))
|
|
|
|
;; 3.22 c
|
|
(defun myfun (a b)
|
|
(list (list a) b))
|
|
|
|
;; 3.22 d
|
|
(defun firstp (item list)
|
|
(equal item (first list)))
|
|
|
|
;; 3.22 e
|
|
(defun mid-add1 (list)
|
|
(cons
|
|
(car list)
|
|
(cons (+ 1 (cadr list))
|
|
(cddr list))))
|
|
|
|
;; 33.2 f
|
|
(defun f-to-c (farenheit-temp)
|
|
(/ (* 5 (- farenheit-temp 32)) 9))
|
|
|
|
(symbol-name `equal)
|
|
(symbol-function `equal)
|
|
|
|
(symbol-name `lambda)
|
|
(symbol-function `lambda)
|
|
|
|
(eval (list `cons t nil))
|
|
|
|
;;; equivalence of COND, IF, AND & OR - conditionals
|
|
|
|
;; (and x y z w)
|
|
|
|
;; (equal 1 1 1)
|
|
|
|
(setq
|
|
x 1
|
|
y nil
|
|
z 1
|
|
w 1)
|
|
|
|
(cond
|
|
((not x) nil)
|
|
((not y) nil)
|
|
((not z) nil)
|
|
((not w) nil)
|
|
(t t))
|
|
|
|
(defun boilingp (temp scale)
|
|
(cond ((and (equal scale `celsius)
|
|
(> temp 100)) t)
|
|
((and (equal scale `farenheit)
|
|
(> temp 212)) t)))
|
|
|
|
(defun boilingp-2 (temp scale)
|
|
(or
|
|
(and (equal scale `celsius) (> temp 100))
|
|
(and (equal scale `farenheit) (> temp 212))))
|
|
|
|
(cond)
|
|
|
|
;; 4.28
|
|
(if (oddp 5) (evenp 7) `foo)
|
|
(or (and (oddp 5) (evenp 7)) `foo)
|
|
;; not sure what's up with that
|
|
;; was that attempt to rewrite if into or&and?
|
|
;; So, that written correctly! I get stops because of forced debugger!
|
|
;; (step (eval (or (and (oddp 5) `(evenp 7)) ``foo)))
|
|
(eval `(evenp 7))
|
|
(eval ``foo)
|
|
|
|
|
|
(step (if (oddp 5) `yes `no))
|
|
|
|
(defun my-abs (x)
|
|
(if (< x 0) (- x) x))
|
|
|
|
(step (my-abs 15))
|
|
|
|
;;; variables & side-effects
|
|
(defun price-change (old new)
|
|
(let* ((diff (- new old))
|
|
(proportion (/ diff old))
|
|
(percentage (* proportion 100.0)))
|
|
(list `widgets `changed `by percentage `percent)))
|
|
|
|
;;; 5.6 die exercise
|
|
(defun throw-die ()
|
|
"Return random value [1 6]."
|
|
(+ 1 (random 6)))
|
|
|
|
(defun throw-dice ()
|
|
"Return list of 2 random die trows"
|
|
(list (throw-die)
|
|
(throw-die)))
|
|
|
|
(defun snake-eyes-p (throw)
|
|
"True if both dice in throw equal to 1."
|
|
(and (equal 1 (first throw))
|
|
(equal 1 (second throw))))
|
|
|
|
(defun boxcars-p (throw)
|
|
"True if both dice in throw equal to 6."
|
|
(and (equal 6 (first throw))
|
|
(equal 6 (second throw))))
|
|
|
|
(defun instant-win-p (throw)
|
|
"True if sum of dice in throw is 7 or 11"
|
|
(let ((sum (+ (first throw) (secon throw)))
|
|
(special-values (list 7 11)))
|
|
nil))
|
|
|
|
;; they meant type of word that is an article
|
|
(setq articles `(the a an))
|
|
(defun contains-article-p-1 (list)
|
|
"Check whether article contains in the list."
|
|
(intersection articles list))
|
|
|
|
(setq test-sentence `(we will rock the boat))
|
|
|
|
;; checks for each article
|
|
(mapcar (lambda (article)
|
|
(member article test-sentence)
|
|
) articles)
|
|
|
|
;; attempt to fold them into single boolean with or
|
|
(apply `or (mapcar (lambda (article)
|
|
(member article test-sentence)
|
|
) articles))
|
|
|
|
(step (apply `+ `(1 2 3)))
|
|
(apply `equal `(2 3))
|
|
(equal 2 3)
|
|
(or nil nil t)
|
|
(apply `or `( nil nil t))
|
|
(step (apply `or (list nil nil nil)))
|
|
|
|
(setq comparing-sentence `(large red shiny kube -vs- small shiny red four-sided pyramid))
|
|
|
|
(list
|
|
(length (intersection
|
|
(cdr (member `-vs- comparing-sentence))
|
|
(cdr (member `-vs- (reverse comparing-sentence)))))
|
|
`common `features)
|
|
|
|
;;; 6.9 programming with tables (as lists)
|
|
(setq table1 `((object1 large green shiny cube)
|
|
(object2 small wihte dull cube)
|
|
(object3 large red shiny pyramid)
|
|
(object3 green shiny sphere)))
|
|
|
|
(setf quality-table
|
|
`((green . color)
|
|
(red . color)
|
|
(white . color)
|
|
(cube . shape)
|
|
(pyramid . shape)
|
|
(sphere . shape)
|
|
(shiny . luster)
|
|
(dull . luster)
|
|
(large . size)
|
|
(small . size)
|
|
))
|
|
|
|
(defun quality (x)
|
|
"Get from hardcoded table."
|
|
(cdr (assoc x quality-table))
|
|
)
|
|
|
|
(defun description (key)
|
|
"Get description of object from hardcoded table."
|
|
(cdr (assoc key table1)))
|
|
|
|
(description `object2)
|
|
;; notion of ~sublis~ function instead of mapcar for getting types of properties
|
|
|
|
(defun differences (x y)
|
|
"Get different properties from hardcoded table."
|
|
(set-exclusive-or (description x)
|
|
(description y)))
|
|
|
|
(differences `object1 `object2)
|
|
|
|
|
|
(remove-duplicates (sublis quality-table (differences `object1 `object2)))
|
|
|
|
;;; 6.35 finite state automata
|
|
|
|
(setq nerd-states `((sleeping . eating)
|
|
(eating . waiting-for-a-computer)
|
|
(waiting-for-a-computer . programming)
|
|
(programming . debugging)
|
|
(debugging . sleeping)))
|
|
|
|
(defun nerdus (current-state)
|
|
"Return next state for the nerdus in the provided CURRENT-STATE."
|
|
(cdr (assoc current-state nerd-states)))
|
|
|
|
(nerdus `programming)
|
|
|
|
(defun sleepless-nerd (current-state)
|
|
"Nerd that never sleeps."
|
|
;; consequtive `sleep -> sleep` considered to be impossible
|
|
(let ((possible-state (nerdus current-state)))
|
|
(if (equal possible-state `sleeping)
|
|
(nerdus `sleeping) possible-state)))
|
|
|
|
(sleepless-nerd `sleeping)
|
|
(sleepless-nerd `debugging)
|
|
|
|
(nerdus `playing-guitar)
|
|
|
|
(defun nerd-on-caffeine (current-state)
|
|
"Advancing two states in one step."
|
|
(nerdus (nerdus current-state)))
|
|
|
|
(nerd-on-caffeine `sleeping)
|
|
|
|
;; nested lists are trees and there are functions that can be used on them
|
|
(subst `bb `aa `(In this list symbol aa would be substituted))
|
|
;; args are NEW OLD TREE
|
|
;; and whole tree structure is checked:
|
|
|
|
(subst `bb `a `((a tree) In this list symbol (a hatter) aa would be substituted (a test)))
|
|
|
|
;; sublis takes many substitutions, instead of first two args, the plist
|
|
(defun royal-we (sentence)
|
|
"Substitute all I to We."
|
|
(subst `we `i sentence))
|
|
|
|
;;; eq compares addresses, so lists would not be eq
|
|
;;; equal compares elements of the lists
|
|
;; symbols are singletons, so using ~eq~ is ok
|
|
;; numbers might not be primitive in lisp implementations!
|
|
;;
|
|
;; eql - compares addresses in general case, for numbers: if of the same type compares values
|
|
(eql 3 3)
|
|
(eql 3 3.0)
|
|
;; to test value of the numbers across types
|
|
;; but works only with numbers, ok!
|
|
(= 3 3.0)
|
|
|
|
|
|
;;; Keyword arguments
|
|
:keyword-symbol ; evaluates to self, cannot change value
|
|
keyword-symbol ; different and not equal to actual keyword
|
|
(symbolp :keyword)
|
|
(keywordp :keyword)
|
|
(keywordp `keyword)
|
|
|
|
;;; 7.3 Applicative programming
|
|
;; one of the styles, along with recursive and iterative
|
|
|
|
(funcall #'cons 'a 'b)
|
|
(setf fn #'cons)
|
|
fn
|
|
(type-of fn)
|
|
(funcall fn 'c 'd)
|
|
|
|
;; using mapcar
|
|
(defun squaring (x)
|
|
"Square input."
|
|
(* x x))
|
|
(squaring 9)
|
|
(squaring '(1 2 2 3))
|
|
|
|
(mapcar #'squaring '(1 2 2 3 9))
|
|
|
|
(mapcar #'zerop '(20 340 0 -5 -6))
|
|
|
|
(mapcar #'(lambda (x) `(hi there ,x))
|
|
'(joe fred martha))
|
|
;; 195
|
|
(funcall #'(lambda (x)
|
|
(or (equal x t)
|
|
(equal x nil))) 1)
|
|
|
|
(defun half (x)
|
|
""
|
|
(/ x 2.0))
|
|
|
|
(defun average (x y)
|
|
""
|
|
(+ (half x) (half y)))
|
|
|
|
(defun fact (n)
|
|
""
|
|
(cond ((zerop n) 1)
|
|
(t (* n (fact (- n 1))))))
|
|
|
|
(fact 4)
|