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"