Lecture #9

Preview:

DESCRIPTION

Lecture #9. 142-151, sections 2.3.1, 2.3.2. Symbol: a primitive type. constructors: (quote alpha) Selectors: none Methods: symbol? : anytype -> boolean eq? ; discuss in a minute (symbol? (quote x)) ==> #t. eq?. - PowerPoint PPT Presentation

Citation preview

מבוא מורחב1

Lecture #9

142-151, sections 2.3.1, 2.3.2

מבוא מורחב2

Symbol: a primitive type

constructors: (quote alpha)

Selectors: none

Methods: symbol? : anytype -> boolean

eq? ; discuss in a minute

(symbol? (quote x)) ==> #t

מבוא מורחב3

eq?

A primitive procedure that returns #t if its two arguments are the same object

(eq? (quote eps) (quote eps)) ==> #t

(eq? (quote delta) (quote eps)) ==> #f

(eq? (cons 1 2) (cons 1 2)) #f

Eq? Can be used for any type except numbers or strings. One should use = for equality of numbers.

מבוא מורחב4

Symbols are ordinary values

In particular we can form list of symbols.

(list 1 2) ==> (1 2)

(list (quote delta) (quote gamma)) ==> (delta gamma)

symbolgamma

symboldelta

מבוא מורחב5

Syntactic Sugar.

Expression: Rewrites to:

1. (quote (a b)) (list (quote a) (quote b))

2. (quote ()) nil

3. (quote (1 (b c)))

(list (quote 1) (quote (b c)))

(list 1 (quote (b c)))

(list 1 (list (quote b) (quote c)))

(1 (b c))

4. 'a is shorthand for (quote a) '(1 (b c)) (quote (1 (b c)))

מבוא מורחב6

Your turn:

(define a 2) (define b 5)

(+ a b) ==>

'(+ a b) ==>

(+ 'a b) ==>

(list '+ a b) ==>

(list + ‘a b) ==>

(eq? '(cons 1 2) '(cons 1 2)) #f

7

(+ a b)

([proc#..] a 3) - error

(+ 2 5)

([procedure #…] a 5)

מבוא מורחב7

Summary so far

• symbol is a primitive type• the special form quote is its constructor• quoting the same name always returns the same object• the primitive procedure eq? tests for sameness

מבוא מורחב8

Manipulating lists and trees of symbols

מבוא מורחב9

Example 1: memq

(define (memq item x) (cond ((null? x) #f) ((eq? item (car x)) x) (else (memq item (cdr x)))))

(memq 'a '(b a b c)) =>

(memq 'a '((a b) b c)) =>

(memq 'a ‘((a b) b a (c a) d)) =>

(a b c)

#f

(a (c a) d)

If item does not appear in x, returns falseOtherwise – returns the sublist beginning with item

מבוא מורחב10

Example 2: rember

(define (rember item x) (cond ((null? x) ‘()) ((eq? item (car x))(cdr x)) (else (cons (car x) (rember item (cdr x))))))

(rember 'a '(d a b c a)) =>

(rember 'b '(a b c)) =>

(rember 'a '(b c d)) =>

(d b c a)

(a c)

(b c d)

Removes the first occurrence of item in x.

11

Example 3: rember*

(define (rember* a x) (cond ((null? x) ‘()) ((atom? (car x)) (cond ((eq? (car x) a)(rember* a (cdr x))) (else (cons (car x) (rember* a (cdr x)))))) (else (cons (rember* a (car x)) (rember* a (cdr x))))))

(rember* 'a '(a b)) =>

(rember* 'a '(a (b a) c (a)) =>

(b)

((b) c ())

Recursively removes all occurances of a

מבוא מורחב12

An example: symbolic differentiation

מבוא מורחב13

Symbolic differentiation

(deriv <expr> <with-respect-to-var>) ==> <new-expr>

(deriv '(+ x 3) 'x) ==> 1

(deriv '(+ (* x y) 4) 'x) ==> y

(deriv '(* x x) 'x) ==> (+ x x)

The expressions we deal with: x+y x+5 2x (x+5) + 2 x y

מבוא מורחב14

Step 1: Legal expressions.

First we have to choose what expressions we work with,And how we represent them.

Suppose we allow addition and multiplication.

Do we accept x+y or (+ x y) ?What about x+y+z and (+ x y z) ?Do we interpret x+ y * z as (x+y)*z or as x+(y*z) ?

How do we represent the output? Are we trying to simplify the output.

מבוא מורחב15

Step 1: Legal Expressions- formal

Expr = SimpleExpr | CompoundExpr

SimpleExpr = number | symbol

CompoundExpr = LIST( OPERATOR, Expr, Expr )

Operator = +|*

מבוא מורחב16

Step 2: Breaking the problem to smaller subproblems

• Base case: (corresponds to SimpleExpr)• deriv constant dx = 0• deriv variable dx = 1 if variable is the same as x

= 0 otherwise

• Induction step: (corresponds to CompoundExpr)

• (f+g)’ = f’ + g’ • (f*g)’ = f * g’ + g * f’

מבוא מורחב17

Step 3: An algorithm assuming an abstract interface.(define deriv (lambda (expr var)

(cond

((number? expr) 0)

((variable? expr) (if (eq? expr var) 1 0))

((sum-expr? expr)

(make-sum (deriv (addend expr) var)

(deriv (augend expr) var)))

((product-expr? expr)

(make-sum

(make-product (augend expr)

(deriv (addend expr) var))

(make-product (addend expr)

(deriv (augend expr) var)))

(else (error "unknown expression" expr))))

מבוא מורחב18

Step 4: The underlying interface

Constructors:

make-product

make-sum

Methods:

number?

variable?

sum-expr?

product-expr?

Selectors:

addend

augend

מבוא מורחב19

Step 5: The underlying interface – constructors and selectors.

We represent constants with integers.

We represent symbols with (quote ..)

And the selectors:

(define (addend expr) (cadr expr))

(define (augend expr) (caddr expr))

We define the constructors:

(define (make-sum e1 e2) (list '+ e1 e2))

(define (make-product e1 e2) (list '* e1 e2))

מבוא מורחב20

Step 5: The underlying interface – methods.

(define (sum-expr? expr) (and (pair? expr)

(eq? (car expr) '+)))

(define (variable? expr) (and (not (pair? expr))

(symbol? expr)))

(define (product-expr? expr) (and (pair? expr)

(eq? (car expr) ‘*)))

מבוא מורחב21

Writing, Debuging, Testing…

(deriv 5 ‘x) 0(deriv ‘x ‘x) 1 (deriv ‘x ‘y) 0…

(deriv ‘(+ x y) ‘x) (+ 1 0)(deriv ‘(+ x y) ‘z) (+ 0 0)

(deriv '(* (+ x y) (- x y)) 'x) unknown expression (- x y)

(deriv '(* (+ x y) (+ x (* -1 y))) 'x) (+ (* (+ x (* -1 y)) (+ 1 0)) (* (+ x y) (+ 1 (+ (* y 0) (* -1 0)))))

מבוא מורחב22

We would like to simplify expressions.

Instead of the expression (+ (* (+ x (* -1 y)) (+ 1 0)) (* (+ x y) (+ 1 (+ (* y 0) (* -1 0)))))

We would like to have 2x

What should we change?

How easy is it to make the change?

מבוא מורחב23

We change make-sum and make-product

It’s easier to change a well-written code.

(define (make-sum a1 a2) (cond ((and (number? a1) (= a1 0)) a2) ((and (number? a2) (= a2 0)) a1) ((and (number? a1) (number? a2)) (+ a1 a2)) (else (list '+ a1 a2))))

(define (make-product a1 a2) (cond ((and (number? a1) (= a1 0)) 0) ((and (number? a2) (= a2 0)) 0) ((and (number? a1) (= a1 1)) a2) ((and (number? a2) (= a2 1)) a1) ((and (number? a1) (number? a2)) (* a1 a2)) (else (list ‘* a1 a2))))

מבוא מורחב24

Testing again..

(deriv '(* (+ x y) (+ x (* -1 y))) 'x) (+ (+ x (* -1 y)) (+ x y))

This is an improvement.

There is still a long way to go….

מבוא מורחב25

Allowing (- x y)

(define (make-minus a1 a2) (cond ((and (number? a1) (= a1 0)) a2) ((and (number? a2) (= a2 0)) a1) ((and (number? a1) (number? a2)) (+ a1 a2)) (else (list ‘- a1 a2))))

(define (minus-expr? expr) (and (pair? expr)

(eq? (car expr) ‘-)))

מבוא מורחב26

Allowing x^k, …. ,1/x, (ln x)

(define (ln-expr? expr) (and (pair? expr)

(eq? (car expr) ‘ln)))

(define deriv (lambda (expr var)

(cond …

((minus-expr? expr)

((ln-expr? expr)

)..)

מבוא מורחב27

Allowing (+ x y z … w) (* x y z … w)

How about the following change:

(define (addend expr) (cadr expr))

(define (augend expr)

(let ((first (car expr))

(second (cadr expr))

(rest (cddr expr)))

(cond ((> (length rest) 1) (cons first rest))

((= (length rest) 1) (car rest)))))

מבוא מורחב28

Testing..

> (deriv '(* x y z w x t y ) 't)(* x (* y (* z (* w (* x y)))))> (deriv '(* x y z w x t y) 'x)(+ (* y z w x t y) (* x (* y (* z (* w (* t y))))))

> (deriv '(+ x y z w a b c x y z e r t ) 'y)2> (deriv '(+ x y z w a b c x y z e r t ) 'f)0

מבוא מורחב29

Guidelines

• Carefully think about • the problem • type of data• The algorithm.

• Identify • Constructors • Selectors, • And the methods you need from your data.

• Use data abstractions.• Respect abstraction barriers.

• Avoid nested if expressions, complicated procedures and always use good names.