;;; Remember, even though it looks like three characters ;;; are just getting echoed, there is a translation from ;;; three characters to an internal data structure, then ;;; back to some characters that get printed. USER(1): #\a #\a ;;; For every data type there is a function that answers ;;; whether its argument is a member USER(3): (numberp 3) T USER(4): (numberp #\x) NIL USER(5): (ratiop 3) NIL ;;; This also tells you what data type an object is, ;;; but it's better to use INSPECT (see below). USER(6): (type-of 3) FIXNUM USER(7): (type-of #\x) CHARACTER ;;; The INSPECT function will give you information about ;;; the data object---it is just for debugging purposes USER(8): (inspect #\x) character #\x [#x000003c0] [1i] USER(9): (inspect "abc") A simple-string (3) "abc" @ #x106915e2 0-> The field #xa 1-> The field #xb 2-> The field #xc ;;; Here is a little example to show you that ;;; you can recursively inspect an object. We ;;; will create an object that is a structure with ;;; two fields, then inspect the object and ;;; look at its two fields ;;; First we define the structure (more on this later) [2i] USER(13): (defstruct point x-coord y-coord) POINT ;;; Now we make an instance of the structure. (This ;;; is equivalent to calling the class constructor in ;;; C++.) [2i] USER(14): (make-point :x-coord 3 :y-coord 4) #S(POINT :X-COORD 3 :Y-COORD 4) ;;; Now we'll look at the object we just created. Note ;;; the use of the asterisk * which refers to "the last ;;; object returned by the read-eval-print loop [2i] USER(15): (inspect *) POINT structure instance @ #x1069ee6a = #S(POINT ...) 0 excl-type ----> Bit field: #x0f 1 structure-name -> The symbol POINT 2 X-COORD ------> fixnum 3 [#x00000018] 3 Y-COORD ------> fixnum 4 [#x00000020] ;;; Now that we're inspecting the object, we can also ;;; inspect its "X-COORD" and "Y-COORD" fields [3i] USER(16): :i x-coord fixnum 3 [#x00000018] [3i] USER(17): :reset ;;; One small correction from last time: I said that ;;; the language was not case sensitive. That's not exactly ;;; true, since case matters for individual characters and ;;; within strings. USER(22): "aBc" "aBc" USER(23): "ABC" "ABC" USER(24): (equal "aBc""ABC") NIL USER(25): #\; #\; ;;; Here's an example where we constructed a string then ;;; extracted its first element (a character). Notice ;;; how that character prints. USER(27): (elt "Hi mom" 0) #\H ;;; Comments: semicolon is the comment character, and it causes ;;; the reader to ignore all characters from the semicolon to ;;; the end of the current line. USER(28): ; USER(28): ; This is a comment ;;; Certain non-print characters have their own special names: ;;; for example, #\space reads in as a single character, the ;;; space character. USER(28): #\space #\space ;;; Here's what happens when we try to read in a character with a ;;; special name, but there's no special character named ABC. ;;; The reader gives us an error. USER(29): #\abc Error: Meaningless character name aBC [condition type: READER-ERROR] [1] USER(30): :res ;;; Now to symbols. The first thing we try is to type in the ;;; name of a symbol. The evaluator tries to access the symbol's ;;; binding, and there is none. That causes an error. ;;; The important point is that symbols are the first objects ;;; that are not self-evaluating. A symbol evaluates to its ;;; binding. USER(31): fred Error: Attempt to take the value of the unbound variable `FRED'. [condition type: UNBOUND-VARIABLE] ;;; This is a hack that will tell you whether a symbol *has* a ;;; binding. YOU SHOULD NEVER USE THIS IN YOUR CODE!!!! [1] USER(32): (boundp 'fred) NIL ;;; This is how we establish a binding for a symbol. Now it's bound, ;;; and it evaluates to its bindin. [1] USER(33): (setf fred 3) 3 [1] USER(34): (boundp 'fred) T [1] USER(35): fred 3 ;;; Now we bind two symbols to numbers and invoke a function to add them. [1] USER(36): (setf ethyl 6) 6 [1] USER(37): (+ fred ethyl) 9 ;;; Suppose we want to inspect the symbol FRED. The first way we ;;; tried accessed Fred's binding, but not Fred itself. So we ;;; get to look at a ratio, but not the symbol. USER(40): (setf fred 2/3) 2/3 USER(41): (inspect fred) RATIO object @ #x106b3fda = 2/3 0 excl-type ----> Bit field: #x43 1 numerator ----> fixnum 2 [#x00000010] 2 denominator --> fixnum 3 [#x00000018] ;;; So here is how we get to the symbol itself: by putting ;;; a single quote in front of the symbol (called "quoting the ;;; symbol") we make it so it is not evaluated. 'FRED evaluates ;;; to the symbol FRED whereas FRED evaluates to whatever FRED is ;;; bound to. [1i] USER(43): 'fred FRED ;;; Now we can inspect the symbol itself: [1i] USER(44): (inspect 'fred) The symbol FRED @ #x1074bd6f which is an INTERNAL symbol in the COMMON-LISP-USER package 0 flags --------> Bit field: #x0000 1 hash ---------> Bit field: #x2c0d 2 value --------> RATIO object = 2/3 3 reserved -----> Bit field: #x00000000 4 package ------> The COMMON-LISP-USER package 5 func-start ---> Bit field: #x00000000 6 function -----> # 7 name ---------> A simple-string (4) "FRED" 8 plist --------> The symbol NIL ;;; You can actually quote anything, but numbers are self-evaluating ;;; so '3 is exactly the same as 3. Both evaluate to the number 3. USER(46): '3 3 USER(47): fred 2/3 USER(48): 'fred FRED ;;; This is what I meant by case not mattering: when you type ;;; in a symbol name, the reader converts it upper case. USER(49): 'fred FRED USER(50): 'fReD FRED ;;; But the two symbols are still equal. USER(51): (equal 'fred 'FrEd) T ;;; One last little fact. A symbol can be used both as a ;;; name for a variable and as a name for a function simultaneously. ;;; There is no conflict between the two: a symbol is called as a function ;;; only if it appears at the beginning of a list. USER(52): (defun fred () "I am fred") FRED ;;; This uses FRED as a variable USER(53): fred 2/3 ;;; This uses FRED as a function USER(54): (fred) "I am fred" ;;; By Inspecting the symbol we can see both its VALUE binding ;;; and its FUNCTION binding. They are two separate fields in ;;; the data structure. USER(55): (inspect 'fred) The symbol FRED @ #x1074bd6f which is an INTERNAL symbol in the COMMON-LISP-USER package 0 flags --------> Bit field: #x0000 1 hash ---------> Bit field: #x2c0d 2 value --------> RATIO object = 2/3 3 reserved -----> Bit field: #x00000000 4 package ------> The COMMON-LISP-USER package 5 func-start ---> Bit field: #x00000000 6 function -----> # 7 name ---------> A simple-string (4) "FRED" 8 plist --------> The symbol NIL [1i] USER(56): :res