;(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"