Lisp Internals A problem with lists In Lisp
Lisp Internals
A problem with lists • In Lisp, a list may “contain” another list – For example, (A (B C)) contains (B C) • So, how much storage do we need to allocate for a list? – If any list can contain any other list, there is no limit to the size of storage block we may need – This is impractical; we need another solution 2
Pointers • Instead of actually putting one list inside another, we put a pointer to one list inside another – A pointer is a fixed, known size • This partially solves the problem, but. . . – A list can contain any number of elements – For example, the list ((A)(B)(A)(C)) contains four lists – This still leaves us needing arbitrarily large blocks of storage 3
CAR and CDR • We can describe any list as the sum of two parts: its “head” (CAR) and its “tail” (CDR) – The head is the first thing in the list – The head could itself be an arbitrary list – The tail of a list is another (but shorter) list • Thus, any list can be described with just two pointers • This provides a complete solution to our problem of arbitrarily large storage blocks 4
S-expressions • In Lisp, everything is an S-expression • An S-expression is an atom or a list • You can think of these as using two different kinds of storage locations--one kind for atoms, another kind for the parts of a list – This is an oversimplification, but it will do for now 5
Atoms • An atom is a simple thing, and we draw it in a simple way: HELLO ABC NIL • Sometimes we don’t bother with the boxes: HELLO ABC NIL 6
Lists • A list has two parts: a CAR and a CDR • We draw this as a box , called a cons cell, with two compartments, called the car field and the cdr field car field cdr field • In each of these compartments we put an arrow pointing to its respective value: value of car value of cdr 7
Example I (A) A NIL 8
Example II (ABC) A (B C) B A B (C) C NIL 9
Example III ((A) B) A NIL B NIL 10
Example IV ((A B) (C D)) A NIL B NIL C D NIL 11
Dotted pairs • In a simple list, every right-pointing arrow points to a cons cell or to NIL • If a right-pointing arrow points to an atom, we have a dotted pair (A. B) A B 12
Lisp lists are implemented with dotted pairs (A) = = A (A. NIL) NIL • Therefore, (A) = (A. NIL) • All structures in Lisp can be created from atoms and dotted pairs 13
Example V ((A. B). (C. D)) A B C D 14
Writing dotted pairs • A dotted pair is written (and printed) using parentheses and a dot: (A. B) • If the CDR of a dotted pair is NIL, the dot and the NIL are omitted: (A. NIL) = (A) • If the CDR is another cons cell, Lisp doesn’t print the dot or the parentheses – (A. (B. (C. NIL))) = (A B C) – (A. (B. (C. D))) = (A B C. D) 15
Efficiency of CDR Suppose L is the list (A B C D E) Then (CDR L) is the list (B C D E) Isn’t it expensive to create this new list? Answer: NO! It’s incredibly cheap! Lisp just copies a pointer: • • • (CDR L) L A (B C D E) 16
Efficiency of CAR and CONS • CAR is just like CDR; you just copy a pointer • CONS takes more work; you have to allocate and fill one cons cell Here’s the cons cell we add to create the list (A B) A Here’s the atom A B NIL Here’s the list (B) 17
Sharing structure • List L and list (CDR L) are said to share structure • But if L = (A B C D E) and M = (CDR L), then when you change L, won’t M be changed? • Yes, but. . . – this is where the real genius of Lisp comes in. . . • You never change L ! • None of the basic functions ever change anything that’s already there • Only CONS adds anything • The result is an extraordinarily efficient language! 18
Memory • If you only add structure, and never change or delete anything, won’t you run out of memory? • Lisp uses garbage collection to recover structures that you are no longer using – More convenient for the programmer – Safer (less subject to human error) – Extremely effective in general 19
Java isn’t Lisp • Although Lisp’s way of handling lists is elegant and efficient, it’s not the only way – Modifying the middle or end of a list is expensive • There are many ways we might implement lists in Java • Lisp’s implementation of lists is a great example, but not necessarily the final word 20
A possible Java implementation class Cell { } class Atom extends Cell { String value; Atom(String value) { // constructor this. value = value; } } class Cons. Cell extends Cell { Cell car; Cell cdr; Cons. Cell(Cell car, Cell cdr) { // constructor this. car = car; this. cdr = cdr; } 21 }
Another possible implementation class Cell { boolean is. Atom; String value; Cell car, cdr; Cell(String value) { // constructor is. Atom = true; this. value = value; } Cell(Cell car, Cell cdr) { // constructor is. Atom = false; this. car = car; this. cdr = cdr; } } 22
Implementing the functions I class Lisp { static Cell car(Cell c) { return c. car; } static Cell cdr(Cell c) { return c. cdr; } static Cell cons(Cell c 1, Cell c 2) { return new Cell(c 1, c 2); } 23
Implementing the functions II static boolean atom(Cell c) { return c. is. Atom; } static boolean eq(Cell c 1, Cell c 2) { return c 1. value. equals(c 2. value); } } 24
The End 25
- Slides: 25