lisp internals. 2 a problem with lists in lisp, a list may “contain” another list –for...

25
Lisp Internals

Upload: william-hall

Post on 16-Dec-2015

219 views

Category:

Documents


2 download

TRANSCRIPT

Lisp Internals

2

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

3

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

4

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

5

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

6

Atoms

• An atom is a simple thing, and we draw it in a simple way:

• Sometimes we don’t bother with the boxes:

HELLO ABC NIL

HELLO ABC NIL

7

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

• In each of these compartments we put an arrow pointing to its respective value:

car field cdr fieldcar field

value of car value of cdr

8

Example I

( A )

A NIL A NIL

9

Example II

( A B C )

A (B C)

B (C)

C NIL

A

B

C NIL

10

Example III

BA NIL NIL

((A) B)

11

Example IV

B

A

NIL

NIL

C

NIL

D

((A B) (C D))

12

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

13

Lisp lists are implemented with dotted pairs

• Therefore, (A) = (A . NIL)• All structures in Lisp can be created from

atoms and dotted pairs

( A ) =

A NIL

= (A . NIL)

14

Example V

A B C D

((A . B) . (C . D))

15

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)

16

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:

A (B C D E)

L (CDR L)

17

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

A

Here’s the atom A B NIL

Here’s the list (B)

Here’s the cons cell we add to create the list (A B)

18

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!

19

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

20

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

21

A possible Java implementation class Cell { }

class Atom extends Cell {String value;Atom(String value) { // constructor

this.value = value;}

}

class ConsCell extends Cell {Cell car;Cell cdr;ConsCell(Cell car, Cell cdr) { // constructor

this.car = car;this.cdr = cdr;

}}

22

Another possible implementation class Cell {

boolean isAtom;String value;Cell car, cdr;

Cell(String value) { // constructorisAtom = true;this.value = value;

} Cell(Cell car, Cell cdr) { // constructor

isAtom = false;this.car = car;this.cdr = cdr;

}}

23

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 c1, Cell c2) { return new Cell(c1, c2);}

24

Implementing the functions II

static boolean atom(Cell c) { return c.isAtom;}

static boolean eq(Cell c1, Cell c2) { return c1.value.equals(c2.value);}

}

25

The End