;; Remember that that a list is a string of cons cells ;; (cons 1 (cons 2 (cons 3 nil))) ;; >> (1 2 3) ;; but if we do it a bit different: ;;(cons 1 (cons 2 3)) ;; >> (1 2 . 3) A bit different ;; This dot notation is lisp saying: ;; I tried to print this structure you entered using list notation ;; but the last item in the list didn't contain the usual nil ;; I expected; instead, it contained 3 ;; A list that ends in something other than nil is refeered to as a doted list ;; dotted lists aren't that useful of a tool ;; It would be unusual for a lisp programmer to store data in one ;; However, given the pervasiveness of cons cells in Lisp, ;; you will frequently encounter a non-nil value at the end of a chain of ;; cons cells. ;; That's why you should become familiar with dotted lists, even if you never ;; Use them directly ;; A proper list could be written in dot notation ;; '(1 . (2 . (3 . nil))) ;; Thinking of it like this shows us why lisp is forced to show ;; the final cons cell ;; One common use for dotted lists is to elegantly represent pairs ;; (cons 2 3) ;; >> (2 . 3) ;; Creating pairs like this is conveient and efficient ;; we can extract members from the pair using standard car and cdr commands ;; efficient because Lisp only needs a single cons cell to connect two items ;; These types of pairs are commonly used in Lisp programs ;; For instance, it could be used to store x/y coors of a point or a key/value ;; pair in a complex data structure ;; Circular lists are a thing. A cons cell can point to an upstream ;; cons cell of a list ;; Before messing with cirular lists, we should do this (setf *print-circle* t) ;; This let's list know we are doing stuff with self-referential data structs ;; and that it needs to be careful when printing on the screen ;; A straightforward way to do this is to use setf to put extra stuff ;; in the first parameter ;; (defparameter foo '(1 2 3)) ;; (setf (cadddr foo) foo) ;; >> #1=(1 2 3 . #1#) ;; Here we created an infinite list of '(1 2 3 1 2 3 1 2 3 ...) ;; by replacing the nil at the end of a simple list with a reference to the ;; list itself ;;Association Lists -- We've used them a bit ;; alist for short ;; An alist consists of key/value pairs stored in a list ;; if a key appears multiple times in a list, it is assumed that the first ;; appearance of the key contains the desired value ;; (defparameter *drink-order* '((bill . double-espresso) ;; (lisa . small-drip coffee) ;; (john . medium-latte))) ;; To look up the order for a person... ;;(assoc 'lisa *drink-order*) ;; >> (LISA . SMALL-DRIP-COFFEE ;; The function searches the list from the beginning to find the desired key ;; Let's say Lisa wants to change her order so... ;; (push '(lisa. large-mocha-with-whipped-cream) *drink-order*) ;; >> ((LISA . LARGE-MOCHA-WITH-WHIPPED-CREAM) ;; (BILL . DOUBLE-ESPRESSO) ;; (LISA . SMALL-DRIP-COFFEE) ;; (JOHN . MEDIUM-LATTE)) ;; Because, by default, the first reference to a key in an alist takes ;; precedence over later references to the same key, ;; the order lisa placed for a small drip is superseded by her more recent one ;; (assoc 'lisa *drink-order*) ;; >> (LISA . LARGE-MOCHA-WITH-WHIPPED-CREAM) ;; However, there is an issue with alists. ;; They are not very efficient way to store and retrieve data ;; Unless dealing with short lists under a doezn items or so ;; alists are typically one of the first tools in the Lispers toolbox ;; they may be replaced by other data structures as a program matures ;; later chapter (9) will explain more ;; Lisp programs are represented with syntax expressions ;; In this format, data is represented using nexted lists ;; often with Lisp symbols at the front of each list ;; explaining the structure of the data ;; Suppose we want to represent the component parts of a house (defparameter *house* '((walls (mortar (cement) (water) (sand)) (bricks)) (windows (glass) (frame) (curtains)) (roof (shingles) (chimney)))) ;; This data structure elegantly captures the hierarchical nature of the parts ;; That make up a house. ;; Since it's structured as a Lisp syntax expression, we can see the lists ;; that make up the levels of the hierarch ;; Also, it follows the convention of a syntax expression by putting a ;; symbol at the front of each list ;; For example, here we have the windows symbol that is then followed by three ;; items representing the glass, frame, and curtains ;; data that is hierarchical and tree-like in nature can be naturally ;; expressed in this way ;; If we move beyond tree-like structures, data stored in a syntax ;; expression can become hard to visualize ;; in mathematics a graph consists of a bunch of nodes connected ;; by deges ;; Such graphs can be stored in cons cells, but they are difficult ;; to visualize. We saw this in Ch 5 when we stored the map of the Wizard's ;; house (which consisted of a directed graph) in two alists ;; One containing the node info, and one containing the edge info ;; It's hard to get a decent understanding of such structs ;; Unfortunaily, data that has the shape of a graph or contains other ;; properties that go beyond simple tree structs are common. ;; Fortunatly, there is an open source tool that optimally arranges this data ;; to create a pretty drawing of a graph ;; see seperate file for graphviz stuff ;; Let's create a graph drawing library, again, see other file