164 lines
4.7 KiB
Plaintext
164 lines
4.7 KiB
Plaintext
;(if '()
|
|
; 'i-am-true
|
|
; 'i-am-false)
|
|
;>> I-AM-FALSE
|
|
;
|
|
;(if '(1)
|
|
; 'i-am-true
|
|
; 'i-am-false)
|
|
;>> I-AM-TRUE
|
|
;
|
|
;This means empty lists are false. This significantly helps with recurison.
|
|
;
|
|
;We can take items from the front of a list and send the rest back
|
|
;(cdr) until the list is empty.
|
|
|
|
;example:
|
|
;
|
|
;(defun my-length (list)
|
|
; (if list
|
|
; (1+ (my-length (cdr list)))
|
|
; 0))
|
|
;
|
|
;(my-length '(list with four symbols))
|
|
|
|
;The empty list is the only false value in common lisp.
|
|
;Any value not equivalent to an empty list will be considered true.
|
|
|
|
(defvar *number-was-odd* nil)
|
|
|
|
(if (oddp 5)
|
|
(progn (setf *number-was-odd* t)
|
|
'odd-number)
|
|
'even-number)
|
|
;progn allows us to do extra commands in a single expression.
|
|
;nly the last evaluation in progn is returned as the value.
|
|
|
|
;Other conditionals have implicit prgn such as when and unless
|
|
|
|
(defvar *number-is-odd* nil)
|
|
(when (oddp 5)
|
|
(setf *number-is-odd* t)
|
|
'odd-number)
|
|
|
|
(unless (oddp 4)
|
|
(setf *number-is-odd* nil)
|
|
'even-number)
|
|
|
|
;The tradeoff is that there is no "else: with these commands.
|
|
;In those cases they just return nil and do nothing.
|
|
|
|
;cond is sometimes considered to be the one true Lisp conditional.
|
|
;It has been around for long long time.
|
|
|
|
(defvar *arch-enemy* nil)
|
|
(defun pudding-eater (person)
|
|
(cond ((eq person 'henry) (setf *arch-enemy* 'stupid-lisp-alien)
|
|
'(curse you lisp alien -- you ate my pudding))
|
|
((eq person 'johnny (setf *arch-enemy* 'useless-old-johnny)
|
|
'(i hope you choked on my pudding johnny))
|
|
(t '(why you eat my pudding stranger ?)))))
|
|
|
|
;Note: "eq" and "eql" Ask if the two things being compared is the same thing.
|
|
;"equal" checks to see if the two thing return the same thing
|
|
;So... something like this:
|
|
|
|
(defun bob ()
|
|
"bob")
|
|
|
|
(let ((x "bob"))
|
|
(eq x (bob)))
|
|
|
|
;Will return False as x's "bob" is different
|
|
;from the "bob" returned by the function
|
|
;Yet
|
|
|
|
(let ((x "bob"))
|
|
(equal x (bob)))
|
|
|
|
;will return true as they both end up returning the same result "bob"
|
|
|
|
(defun pudding-eater (person)
|
|
(case person
|
|
((henry) (setf *arch-enemy* 'stupid-lisp-alien)
|
|
'(curse you lisp alien -- you ate my pudding))
|
|
((johnny) (setf *arch-enemy* 'useless-old-johnny)
|
|
'(i hope you choked on my pudding johnny))
|
|
(otherwise '(why you eat my puding stranger ?))))
|
|
|
|
;This is how we do cases.
|
|
;Unfortunatly, cases are only really useful in the case of matching symbols
|
|
;This is because case uses (eq) to do the comparisons.
|
|
;As noted earlier, this doesn't work well with strings.
|
|
|
|
(and (oddp 5) (oddp 7) (oddp 9))
|
|
;This is how we could use the (and) macro to check of three numbers are odd
|
|
|
|
(or (oddp 4) (oddp 7) (oddp 8))
|
|
|
|
;This is how we can check to see if at least one of the numbers is odd.
|
|
|
|
(or (oddp 4) (setf *is-it-even* t))
|
|
|
|
;This is a way we can use (or) as a conditional.
|
|
;If the first number was odd, it would never make it to the (setf)
|
|
;But, it is even so it does.
|
|
;This is called "shortcut boolean evaluation"
|
|
;This means once Lisp determines that an earlier statement
|
|
;in a list of (or) values is true,
|
|
;It doesn't bother evaluating the rest.
|
|
;Same happens with (AND)
|
|
;If a statement returns false, it doesn't bother checking the rest
|
|
|
|
;Another example, think about saving a document:
|
|
(if *file-modified*
|
|
(if (ask-user-about-saving)
|
|
(save-file)))
|
|
|
|
;could be rewriten as an (and) statement
|
|
|
|
(and *file-modified* (ask-user-about-saving) (save-file))
|
|
|
|
;This is like asking the following
|
|
;Has the file been modified? If true then...
|
|
;Ask the user about saving, did the user's answer return true? If so, then:
|
|
; run the (save-file) function
|
|
|
|
;And of course, the way I probably would have written it in c or something
|
|
|
|
(if (and *file-modified*
|
|
(ask-user-about-saving))
|
|
(save-file))
|
|
|
|
So basically, we could use (and) or (or) as a conditional
|
|
;and put what we want to happen at the end
|
|
|
|
(if (member 1 '(3 4 1 5))
|
|
'one-is-in-the-list
|
|
'one-is-not-in-the-list)
|
|
|
|
>> ONE-IS-IN-THE-LIST
|
|
|
|
;Should be obvious, but member checks if an item is in a list or not.
|
|
;It then returns that item, plus the rest of the list
|
|
;This being a non-empty list returns true, which allows are (if) conditional
|
|
;To chose the "if-True" option of the (if)
|
|
;Remember, lisp blocks only return the last thing it computes
|
|
;That's why it does not return the normal functionality of (member)
|
|
;Could be useful for games.
|
|
|
|
;back to the (eq)/(equal)/(eql) issue...
|
|
;Conra'ds Rule of thumb for compargint Stuff:
|
|
;1. use (eq) to compare symbols
|
|
;2 use (equal) for everything else
|
|
|
|
;Why bother with (eq) at all? Well, apprently it's faster
|
|
|
|
;(equalp) can compare things that are mostly the same. So...
|
|
(equalp "BoB" "bob")
|
|
;will return true and:
|
|
(equalp 1 1.0)
|
|
;will also return true
|
|
|
|
;Oh shit, chapter 5 is exciting. "Building a text game engine"
|