symbolic computation

36
Symbolic Computation Lisp and Scheme are interactive languages Numbers, booleans, and symbols Numerals have numbers as their values The booleans #T and #F Symbols, like PETER, must be assigned a value Predicates e.g., NUMBER?, BOOLEAN? Prefix notation and arithmetic operators Statements have the form (function arg ... arg), e.g., » (+ 2 5) » (NUMBER? 5) » (BOOLEAN? #T)

Upload: briana

Post on 16-Jan-2016

37 views

Category:

Documents


0 download

DESCRIPTION

Symbolic Computation. Lisp and Scheme are interactive languages Numbers, booleans, and symbols Numerals have numbers as their values The booleans #T and #F Symbols, like PETER, must be assigned a value Predicates e.g., NUMBER?, BOOLEAN? Prefix notation and arithmetic operators - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Symbolic Computation

Symbolic Computation

• Lisp and Scheme are interactive languages

• Numbers, booleans, and symbols– Numerals have numbers as their values

– The booleans #T and #F

– Symbols, like PETER, must be assigned a value

• Predicates– e.g., NUMBER?, BOOLEAN?

• Prefix notation and arithmetic operators– Statements have the form (function arg ... arg), e.g.,

» (+ 2 5)

» (NUMBER? 5)

» (BOOLEAN? #T)

Page 2: Symbolic Computation

Symbols & Quotation

• Symbols don’t have values unless assigned» 5

5

» peter

?

• Sometimes a symbol is just a symbol» 'peter

peter

• Giving global values using DEFINE» (define peter 'jackson)

» peter

jackson

Page 3: Symbolic Computation

Lists & Evaluation

• Unless QUOTEd, a list of the form» (S1 S2 S3 ... Sn)

is assumed to represent a call to the function S1 with arguments S2, S3, ..., Sn

• Scheme does the following:– evaluates S1 by looking up its function definition

– evaluates the arguments S2, S3, ..., Sn

– applies the function definition to the evaluated arguments

• Apart from a number of special forms, e.g., conditional statements, all Scheme expressions have this general form

Page 4: Symbolic Computation

Scheme Procedures

• A Scheme procedure is defined using DEFINE– e.g., a function which takes an argument and adds 1 to it

(define increment

(lambda (n) (+ n 1))) – Note lack of type declarations among arguments to

functions

• LAMBDA can be thought of as an abstraction operator– e.g., we turn (+ 10 1) into the increment operation by

replacing number to be incremented by a bound variable

(lambda (n) (+ n 1))

Page 5: Symbolic Computation

Lambda Conversion

• Function application is lambda conversion» ((lambda (n) (+ n 1)) 10)

11

• Converting the lambda expression means:– replacing variables by the values of arguments in the

body of the lambda expression, (+ n 1) becomes (+ 10 1)

– evaluating the body in the context of these variable bindings and returning the result

(define increment (lambda (n) (+ n 1))) allows us to write

» (increment 10)

11

Page 6: Symbolic Computation

The Importance of Lists

• Lists represent both programs and data!

• Three basic operations on lists:– CAR returns the head of a list

» (car '(a b c))

a

– CDR returns the tail of a list

» (cdr '(a b c))

(b c)

– CONS adds an item to the front of a list

» (cons 'a '(b c))

(a b c)

Page 7: Symbolic Computation

Other List Functions

• LIST takes any number of arguments and returns them in a list– E.g.,

» (list 1 2 3)

(1 2 3)

» (list 'a 'b 'c 'd)

(a b c d)

• APPEND copies and joins two lists– E.g.,

» (append '(a b) '(c d e))

(a b c d e)

Page 8: Symbolic Computation

Function Composition

• You can compose functions in Scheme by embedding the list structures of function calls– E.g.,

» (+ (+ 1 2) 3)

6

» (* (+ 2 3) (+ 1 3))

15

» (cons ‘a (cons ‘b ()))

(a b)

» (append '(a b) (append '(c d) '(e f)))

(a b c d e f)

Page 9: Symbolic Computation

Basic Predicates - NULL?

• We need to be able to test if a list is empty– we use NULL? for this, e.g.,

» (null? '(a b c))

#F

» (null? '())

#T

– Scheme and LISP often use the empty list, (), to denote falsity, e.g., you may sometimes see

» (null? '(a b c))

()

– In LISP, the special atom, NIL, also stands for the empty list

Page 10: Symbolic Computation

Basic Predicates - EQ?

• Two expressions are EQ if they evaluate to the same symbols, e.g.,

» (eq? 'a 'a)

#T

» (eq? 2 2)

#T

» (eq? 2 2.0)

#F

» (eq '(a b) '(a b))

#F

» (eq l m) ; after (define l '(a b)) (define m l)

#T

Page 11: Symbolic Computation

Other Equality Tests

• EQV? includes booleans and numbers– E.g.,

» (eqv? 2 2.0)

#T

» (eqv? '(a b) '(a b))

#F

• EQUAL? includes lists also– E.g.,

» (equal? '(a b) '(a b))

#T

Page 12: Symbolic Computation

The Conditional: COND

• The conditional expression has this structure:

(cond

(test1 action1)

(test2 action2)

...

(else default))

(cond

((null? x) NIL)

((number? x) x)

(else (list x)))

Page 13: Symbolic Computation

A Simple Conditional: IF

• You can use IF for a simple if-then-else test– E.g.,

(if (number? x) x

(list x))

• IFs can be nested, but then a COND may be better– E.g.,

(if (null? x) NIL

(if (number? x) x

(list x)))

Page 14: Symbolic Computation

Tail (or Flat) Recursion - APPEND

• Here is a definition of APPEND, using CONS:

(define append

(lambda (l m)

(if (null? l) m

(cons (car l)

(append (cdr l) m)))))

• Note indentation, which makes code more readable

Page 15: Symbolic Computation

More Tail Recursion - REMOVE

• Here is a definition of REMOVE, using CONS

(define remove

(lambda (x l)

(cond ((null? l) NIL)

((eq? x (car l)) (remove x (cdr l)))

(else (cons (car l)

(remove x (cdr l)))))))

• Note use of COND for case analysis

Page 16: Symbolic Computation

Inefficiencies - Naive Reverse

• Here is a naive definition of REVERSE

(define reverse

(lambda (l)

(if (null? l) NIL

(append (reverse (cdr l))

(list (car l))))))

• APPEND copies its arguments & CDRs through its first argument, consuming both time and space

Page 17: Symbolic Computation

Accumulators - Better REVERSE

• A definition of REVERSE that avoids APPEND:

(define reverse (lambda (l) (rev-help l NIL)))

(define rev-help

(lambda (l result)

(if (null? l) result

(rev-help (cdr l)

(cons (car l) result)))))

Page 18: Symbolic Computation

Lists & Trees

• Correspondence between lists and trees– E.g., ((B C) A (D (E F) G)) can be thought of as a tree:

A

B C

D

E F

G

Page 19: Symbolic Computation

Depth-First Tree Search

• Searching sublists before siblings

(define search

(lambda (x l)

(cond ((null? l) NIL)

((atom? (car l))

(or (eq? x (car l)) (search x (cdr l))))

(else (or (search x (car l))

(search x (cdr l)))))))

Page 20: Symbolic Computation

Breadth-First Tree Search

• Searching siblings before sublists

(define search

(lambda (x l)

(cond ((null? l) NIL)

((atom? (car l))

(or (eq? x (car l)) (search x (cdr l))))

(else (or (search x (cdr l))

(search x (car l)))))))

Page 21: Symbolic Computation

Another Tree Recursion Example

• Counting the number of atoms in an embedded list

(define count

(lambda (l)

(cond ((null? l) 0)

((atom? (car l))

(add1 (count (cdr l))))

(else (+ (count (car l))

(count (cdr l)))))))

Page 22: Symbolic Computation

Final Tree Example - Flatten

• FLATTEN takes internal parentheses out of a list

(define flatten

(lambda (l)

(cond ((null? l) NIL)

((atom? (car l))

(cons (car l) (flatten (cdr l))))

(else (append (flatten (car l))

(flatten (cdr l)))))))

Page 23: Symbolic Computation

Procedures As Arguments

• The function (FILTER pred list) removes all elements from list which do not satisfy pred

(define filter(lambda (pred l)

(cond ((null? l) NIL)((atom? (car l)) (if (pred (car l)) (cons (car l) (filter pred (cdr l)))))(else (append (filter pred (car l)) (filter pred

(cdr l)))))))

Page 24: Symbolic Computation

Iteration with Mapping Functions

• (MAP function list) applies function to every member in list and returns the result in a list:– E.g.,

» (map add1 '(1 2 3))

(2 3 4)

• (APPLY function list) applies function to list:– E.g.,

» (apply max '(3 100 45))

100

• Note that function names are not quoted

Page 25: Symbolic Computation

Procedures As Values

• Curried functions: Definition of ADDN

(define addn

(lambda (x)

(lambda (y)

(+ x y))))

• (ADDN X) returns a function which always adds X to its argument

» ((addn 5) 10)

15

Page 26: Symbolic Computation

Lexical Scoping

• Definition of ADDN works because:– All free variables in a lambda expression are assigned

values at the time that the lambda is defined (i.e., evaluated and returned)

– If a free variable has no value, an error is generated

– Bound variables do not receive values until the lambda is applied (i.e., converted)

• This convention is called lexical scoping– In the opposite convention, called dynamic scoping, free

variables have values determined when lambda is applied

– Failure to find a value at run-time generates an error

– Early versions of LISP were dynamically scoped, but Common LISP and Scheme are lexically scoped

Page 27: Symbolic Computation

Binding Environments (I)

• Declaring local variables with LET

(let ((var1 val1) (var2 val2) ... (varN valN))

body)

• Equivalent to the following LAMBDA application

((lambda (var1 var2 ... varN)

body)

val1 val2 ... valN)

Page 28: Symbolic Computation

Binding Environments (II)

• LETREC allows bindings to reference each other

(letrec ((even? (lambda (x)

(or (zero? x) (odd? (sub1 x))))

(odd? (lambda (x)

(and (not (zero? x)) (even? (sub1 x)))))

(odd? 17))

• This is an example of mutual recursion

Page 29: Symbolic Computation

Why We Need LETREC

• This LET statement would generate an error

(let ((x 5) (y (+ x 1)))

(* x y))

because it translates into a LAMBDA application ...

((lambda (x y) (* x y)) 5 (+ x 1))

where ‘x’ is unbound outside of the LAMBDA

Page 30: Symbolic Computation

Procedural Abstraction

• Here is an abstract version of tail recursion

(define tail-recur

(lambda (seed action)

(letrec ((helper

(lambda (l)

(if (null? l) seed

(action (car l) (helper (cdr l)))))))

helper)))

Page 31: Symbolic Computation

Using Procedural Abstraction

• Defining summation function for lists

(define sum (tail-recur 0 +))

• This is equivalent to:

(define sum

(lambda (l)

(if (null? l) 0

(+ (car l) (sum (cdr l)))))))

Page 32: Symbolic Computation

Abstraction of Depth-First Search

• With success criteria & successor function

(define search(lambda (stack next success)

(cond ((null? stack) NIL) ((success (car stack)) (car stack)) (else (search (append (next (car stack))

(cdr stack))

next success)))))

Page 33: Symbolic Computation

Abstraction of Breadth-First Search

(define search

(lambda (stack next success)

(cond ((null? stack) NIL)

((success (car stack)) (car stack))

(else (search

(append (cdr stack)

(next (car stack)))

next

success)))))

Page 34: Symbolic Computation

Better Function Using LETREC

(define search

(lambda (stack next success)

(letrec ((search-help

(lambda (l)

(cond

((null? l) NIL)

((success (car l)) (car l))

(else (search-help

(append l (next (car l))))))))

(search-help stack))))

Page 35: Symbolic Computation

Managing Local State

(define make-light (lambda ()

(let ((color 'red))

(lambda (msg)

(case msg

(show color)

(change

(if (eq? color 'red) (set! color 'green)

(set! color 'red)))

(else (writeln “Message not known”))))))

Page 36: Symbolic Computation

Creating objects & sending messages

(define alight (make-light))<PROCEDURE>

(alight 'show)RED

(alight 'change)GREEN

(alight 'show)GREEN