variations on scheme

37
1 Variations on scheme

Upload: julie-avery

Post on 30-Dec-2015

53 views

Category:

Documents


3 download

DESCRIPTION

Variations on scheme. Variable Declarations: lazy and lazy-memo. Handle lazy and lazy-memo extensions in an upward-compatible fashion.; (lambda (a (b lazy) c (d lazy-memo)) ...) "a", "c" are normal variables (evaluated before procedure application - PowerPoint PPT Presentation

TRANSCRIPT

1

Variations on scheme

2

Variable Declarations: lazy and lazy-memo

• Handle lazy and lazy-memo extensions in an upward-compatible fashion.;

(lambda (a (b lazy) c (d lazy-memo)) ...)

• "a", "c" are normal variables (evaluated before procedure application

• "b" is lazy; it gets (re)-evaluated each time its value is actually needed

• "d" is lazy-memo; it gets evaluated the first time its value is needed, and then that value is returned again any other time it is needed again.

3

Syntax Extensions – Parameter Declarations

(define (first-variable var-decls) (car var-decls))

(define (rest-variables var-decls) (cdr var-decls))

(define declaration? pair?)

(define (parameter-name var-decl)

(if (pair? var-decl) (car var-decl) var-decl))

(define (lazy? var-decl)

(and (pair? var-decl) (eq? 'lazy (cadr var-decl))))

(define (memo? var-decl)

(and (pair? var-decl)

(eq? 'lazy-memo (cadr var-decl))))

4

Controllably Memo-izing Thunks

•thunk – never gets memoized•thunk-memo – first eval is remembered•evaluated-thunk – memoized-thunk that has

already been evaluated

thunk-memo

envexp

evaluated-thunk

result

whenforced

5

A new version of delay-it

• Look at the variable declaration to do the right thing...

(define (delay-it decl exp env)

(cond ((not (declaration? decl))

(l-eval exp env))

((lazy? decl)

(list 'thunk exp env))

((memo? decl)

(list 'thunk-memo exp env))

(else (error "unknown declaration:" decl))))

6

Change to force-it

(define (force-it obj) (cond ((thunk? obj) ;eval, but don't remember it (actual-value (thunk-exp obj) (thunk-env obj))) ((memoized-thunk? obj) ;eval and remember (let ((result (actual-value (thunk-exp obj) (thunk-env obj)))) (set-car! obj 'evaluated-thunk) (set-car! (cdr obj) result) (set-cdr! (cdr obj) '()) result)) ((evaluated-thunk? obj) (thunk-value obj)) (else obj)))

7

Changes to l-apply

• Key: in l-apply, only delay "lazy" or "lazy-memo" params• make thunks for "lazy" parameters• make memoized-thunks for "lazy-memo" parameters

(define (l-apply procedure arguments env) (cond ((primitive-procedure? procedure) ...) ; as before; apply on list-of-arg-values ((compound-procedure? procedure) (l-eval-sequence (procedure-body procedure)

(let ((params (procedure-parameters procedure))) (extend-environment

(map parameter-name params) (list-of-delayed-args params arguments env) (procedure-environment procedure)))))

(else (error "Unknown proc" procedure))))

8

Deciding when to evaluate an argument...

• Process each variable declaration together with application subexpressions – delay as necessary:

(define (list-of-delayed-args var-decls exps env)

(if (no-operands? exps)

'()

(cons (delay-it (first-variable var-decls)

(first-operand exps)

env)

(list-of-delayed-args

(rest-variables var-decls)

(rest-operands exps) env))))

9

Summary

• Lazy evaluation – control over evaluation models• Convert entire language to normal order• Upward compatible extension

– lazy & lazy-memo parameter declarations

10

How do we use this new lazy evaluation?

• Our users could implement a stream abstraction:(define (cons-stream x (y lazy-memo)) (lambda (msg) (cond ((eq? msg 'stream-car) x) ((eq? msg 'stream-cdr) y) (else (error "unknown stream msg" msg)))))

(define (stream-car s) (s 'stream-car))(define (stream-cdr s) (s 'stream-cdr))

OR

(define (cons-stream x (y lazy-memo))

(cons x y))

(define stream-car car)

(define stream-cdr cdr)

11

Stream Object

a thunk-memo

avalue

stream-car

cons-stream

stream-cdr

12

Review

13

Review: Final last spring

אפשרות לטיפול ( meta-circular evaluatorברצוננו להוסיף למשעך המטה-מעגלי )אם . dotted-tail notationבשגרות בעלות מספר ארגומנטים לא קבוע תוך שמוש ב-

ברשימת הפרמטרים של שגרה מופיעה נקודה לפני הפרמטר האחרון אז כאשר קוראים לשגרה זאת יקבלו הפרמטרים שמופיעים לפני הנקודה, אם יש כאלו, את

יקבל האחרון והפרמטר הרגילה, בצורה שאר רשימהערכם מכל שמורכבת הארגומנטים. למשל, אם נשערך

(define (f x y . z) (cons (list x y) z) (f 1 2 3 4)

4יקשר לרשימה ) z ו- 2יקשר ל- y, 1ל- xיקשר fאז בעת הפעלת הפונקציה (. התוצאה שתוחזר תהיה על כן 3

( (1 2) 3 4)

ב- להשתמש שניתן בביטויי dotted-tail notationכמובן את lambdaגם ולהגדיר באופן הבא fהשגרה

(define f (lambda (x y . z) (cons (list x y) z)))

14

שמקבלת כקלט רשימת פרמטרים שכוללת אולי remove-dotכתוב/י שגרה נקודה לפני הפרמטר האחרון. על השגרה להחזיר רשימה בת שני איברים. האיבר הראשון הוא מספר הפרמטרים שמופיעים לפני הנקודה, או המספר הכולל של הפרמטרים אם אין ברשימת הקלט נקודה. האיבר השני ברשימת

הפלט הוא רשימת כל הפרמטרים ללא הנקודה. למשל:

(remove-dot ‘(x y . z)) ( 2 (x y z)) (remove-dot ‘(x y z)) ( 3 (x y z) ) (remove-dot ‘(. x)) ( 0 (x) )

15

(define (remove-dot lst) (cond ((null? lst) (list 0 lst))

((eq? (car lst) ’.) (list 0 (cdr lst))) (else (let ((x (remove-dot (cdr lst)))) (list (+ 1 (car x)) (cons (car lst) (cadr x)))))))

16

mc-eval משתמש בשגרהmake-procedure :שמוגדרת באופן הבא

(define (make-procedure parameters body env) (list ‘procedure parameters body env))

הגדרת את ובו make-procedureשנה/י גם במקרה לטפל parametersכך שתוכל ע"י שייוצר נקודה בתוכה. העצם הפרוצדורלי -makeהוא רשימת פרמטרים עם

procedure .כמקודם ארבע באורך במקום חמש, באורך רשימה להיות צריך ואין במקרה הכולל, הפרמטרים מספר להיות צריך זאת ברשימה השני האיבר האיבר נקודה. יש אם הנקודה, לפני שהופיעו הפרמטרים מספר או נקודה, ברשימה, הראשון האיבר הנקודה(. )ללא הפרמטרים כל רשימת יהיה השלישי

ושני האיברים האחרונים בה יהיו כמקודם.

(define (make-procedure parameters body env) (let ((x (remove-dot parameters))) (list 'procedure (car x) (cadr x) body env)))

17

. nומספר lstשמקבלת רשימה ( split-list lst nהשלם/י את הגדרת השגרה ) nעל השגרה להחזיר רשימה ש- . nהוא לפחות lstניתן להניח שהאורך של

עוד lstאם יש ב- . lstהאיברים הראשונים של nהאיברים הראשונים בה הם שנותרו האיברים רשימת יהיה הפלט ברשימת האחרון האיבר אז איברים,

למשל:. lstב-

(split-list ‘(1 2 3 4) 4) (1 2 3 4) (split-list ‘(1 2 3 4) 2) (1 2 (3 4)) (split-list ‘(1 2 3 4) 0) ((1 2 3 4))

(define (split-list lst n) (if (= n 0) (if (null? lst) '() (list lst)) (cons (car lst) (split-list (cdr lst) (- n 1)))))

18

את לתאר מתבקש את/ה זאת שאלה של הנותרים בסעיפים וכן אולי בשגרות applyב- evalהשינויים שיש לבצע, אם בכלל, ב-

בשגרות נכונה בצורה לטפל ידע שהמשערך בכדי אחרות, . dotted-tail notationשהוגדרו תוך שמוש ב-

בהגדרת שינויים לבצע צורך יש ? evalהאם את תאר כן, אם

השינויים הדרושים.

שינויים בהגדרת צורך לבצע יש ? applyהאם כן, תאר את אם השינויים הדרושים.

19

(define (mc-apply procedure arguments) (cond ((primitive-procedure? procedure) (apply-primitive-procedure procedure arguments)) ((compound-procedure? procedure) (eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) (split-list arguments (procedure-before-dot procedure)) (procedure-environment procedure)))) (else (error "Unknown procedure type -- APPLY" procedure))))

20

האם יש צורך לבצע שינויים בשגרות אחרות ? אם כן, תאר את .השינויים הדרושים.

(define (procedure-before-dot p) (cadr p))(define (procedure-parameters p) (caddr p))(define (procedure-body p) (cadddr p))(define (procedure-environment p) (cadddr (cdr p)))

21

Final last spring

k fהן פונקציות, נסמן ב- את הפונקציה שמתקבלת ע"י הפעלת gו- fאם וב- של f*gפעמים, ההרכבה אם . gו- fאת f(3)אז f(x)=x2למשל,

(x)=f(f(f(x)))=x8 . אם בנוסף לכךg(x)=x+1 2אז(f*g()x(=)x+1 .)

( השגרה מימוש את שגרה ( iterate f nהשלם/י טבעי fשמקבלת nומספר על השגרה להחזיר את העתקת , n=0ומחזירה שגרה שמחשבת את . אם

הזהות.

f(k)

f(n)

(define (iterate f n) (if (= n 0) _______________ ________________________________________))

(define (iterate f n) (if (= n 0) (lambda (x) x) (lambda (x) (f ((iterate f (- n 1)) x)))))

22

Final last spring (Cont)

( השגרה הגדרת את איבר ( duplicate x nהשלם/י xשמקבלת . xשכל איבריה הם nומחזירה רשימה באורך

(define (duplicate x n) ((iterate __________________________) ___ )) (lambda (y) (cons x y)) n) '()

23

Final last spring (Cont)

( השגרה הגדרת את מספר ( int-lst nהשלם/י nשמקבלת (n . . 2 1).ומחזירה את רשימת המספרים

(define (int-lst n) ((iterate ______________________________________________) _________ ))

(lambda (x) (cons (- (car x) 1) x)) (- n 1)) (list n)))

24

Final last spring (Cont)

שמקבלת רשימת ( compose fnsהשלם את מימוש השגרה ).מהצורה fnsזוגות

( (f1 . n1( )f2 . n2( … )fk . nk ) ) כאשרf1,f2,…,fk הן שגרותהם מספרים טבעיים ומחזירה שגרה שמחשבת n1,n2,…,nkו-

f1את(n1)

*f2(n2)

*…*fk(nk )

(define (compose fns) (if (null? fns) ________________ (let ((f1 __________)

(n1 __________) (rest __________))

_____________________________________________ )))

(lambda (x) x) (caar fns)

(cdar fns) (cdr fns) (lambda (x) ((iterate f1 n1) ((compose rest) x)))

25

בשאלה זאת נתאים לכל מספר טבעי רשימה שמורכבת , תתאים הרשימה 0מהספרות שלו )בייצוג העשרוני(. למספר

תתאים 4(’. למספר 1 תתאים הרשימה )1הריקה . למספר (’, וכך הלאה. 1 3 תתאים הרשימה )13(’. למספר 4הרשימה )

)שימו לב שספרת האחדות היא הספרה הראשונה ברשימה(.

-digשמקבלת רשימה, ( increment dig-listממש שגרה )list , שמייצגת מספר מסויםn ומחזירה את הרשימה

. n+1שמייצגת את המספר

26

(define (increment n1) (if (null? n1) '(1) (let ((digit (car n1))) (if (= digit 9)

(cons 0 (increment (cdr n1))) (cons (+ digit 1) (cdr n1))))))

-digשמקבלת רשימה, ( increment! dig-listממש שגרה )list , שמייצגת מספר מסויםn ומחזירה את הרשימה

. n+1שמייצגת את המספר

חדשים רק במידה ויש cons לשגרה זו מותר להגדיר תאי- בכך צורך. לדוגמא:

27

(define (add1! n1) (if (null? n1) '(1) (let ((digit (car n1)))

(if (= digit 9) (begin (set-car! n1 0) (add1! (cdr n1)))

(set-car! n1 (+ digit 1))))) n1)

המכיל את כל המספרים streamהמחזירה , odd-1-digitsממש פרוצדורה מספר אי-זוגי של 1הטבעיים, שבייצוג העשרוני שלהם מופיעה הספרה

פעמים . כל מספר בזרם מיוצג ע"י רשימת ספרותיו בייצוגו העשרוני כמו בסעיפים הקודמים )בסדר ספרות הפוך(.

(stream-car (odd-1-digits)) (1)

(stream-car (stream-cdr (odd-1-digits))) (0 1)

28

(define (odd-1-digits) (define ints (cons-stream ____________

(stream-map _____________________ ))) (stream-filter ______________________________________________ ______________________________________________ ______________________________________________ ints))

‘()add1 ints

(lambda (y) (odd? (accumulate + 0 (filter (lambda (x) (= x 1)) y))))

29

. עץ-חישוב הוא עץ-חישובבשאלה זאת נעסוק במבנה נתונים מופשט הקרוי עץ שבכל צומת פנימי שלו רשומה פונקציה, ושבכל עלה שלו רשום איבר.

רשומות שבהם פנימיים צמתים משני שמורכב עץ-חישוב כדוגמא מוצג בציור . ערכו 5 ו- 9, 4, 3וארבעה עלים שמהם מופיעים המספרים gו- fהפונקציות

של עץ-חישוב נקבע ע"פ ההגדרה הרקורסיבית הבאה. אם עץ-החישוב מורכב ערך מתקבל אחרת, זה. בעלה שרשום כערך מוגדר ערכו אז בודד, מעלה ערכי על עץ-החישוב בשורש שרשומה הפונקציה הפעלת ע"י עץ-החישוב

תתי-העצים של עץ-החישוב. ערכו של עץ-החישוב שמופיע בציור הוא, למשל,

f

g 9 5

43

f(g(3,4),9,5)

30

לצורך טיפול בעצי-חישוב, עומדות לרשותך השגרות הבאות:

(leaf? tree --- ) בודק האם העץtree .מורכב מעלה בודד(one-child? tree --- ) בודק האם לשורש העץtree .בן אחד בלבד(content tree --- ) מחזיר את תוכנו של שורש עץ-החישובtree.(children tree --- ) של תתי העצים של השורש של רשימהמחזיר

tree.(left-child tree --- ) מחזיר את תת העץ השמאלי ביותר שלtree.(rest tree --- העץ ( את העץ treeמחזיר תת הורדת לאחר

השמאלי ביותר שלו.

31

שמקבלת כארגומנט eval-treeהשלם את הגדרת השגרה עץ-חישוב ומחזירה את ערכו

(define (eval-tree tree)

(if (leaf? tree) ____________________________________

_________________________________________________

__________________________________________________))

(content tree)

(apply (content tree) (map eval-tree (children tree)))

32

בעצי-חישוב עתה הוא בוליאנייםנתרכז בוליאני עץ-חישוב .האיברים רק מופיעים שבעליו ו- 0עץ-חישוב ושבצמתיו 1 ,

מחזירה lorכאשר , landו- lorהפנימיים מופיעות רק הפונקציות אם ורק אם לפחות אחד מהארגומנטים שלה הוא 1את הערך

ו- 1 אם ורק אם 1מחזירה את הערך land אחרת, בעוד ש-0, הם שלה הארגומנטים ו- 1כל )גם 0, אחרת. lor וגםland

מקבלות מספר כלשהו של ארגומנטים.( )אינכם נדרשים לממש .(landו- lorאת

בשגרה להשתמש כמובן עצי-חישוב eval-treeניתן לשערך בכדי נסתכל אם בזבזני. מאוד לפעמים הוא זה דבר אך בוליאניים לקבוע שניתן לב נשים הבא, הבוליאני עץ-החישוב על למשל

מבלי בכלל לבדוק את תוכן העלים שתוכנם מסומן 1שערכו הוא בסימן שאלה.

33

or

and 1 ?

?0

34

ניתן לחשב את ערכו של עץ-חישוב בוליאני ע"י באופן כללי בודד, מורכב מעלה האלגוריתם הרקורסיבי הבא: אם העץ החזר את ערך העלה. אחרת, שערך בזה אחר זה, משמאל לימין, את תתי-העצים שמהם מורכב העץ עד שניתן לקבוע

בצורה חד משמעית את ערך העץ.

השגרה של הבאה ההגדרה את eval-bool-treeהשלם עצי-חישוב לשערוך היעיל האלגוריתם את שמממשת

( השגרה לרשותך שעומדת הנח ( lor? treeבוליאניים. העץ בשורש שמופיעה הפונקציה אם היא treeשבודקת

.lorהפונקציה

35

(define (eval-bool-tree tree) (if (leaf? tree) __________________ (let ((tmp (eval-bool-tree ______________ ) ) ) (if (or (one-child? ______________ ) (and (= tmp 1) (lor? _______) ) __________________________ __________________________ __________________________ ))))

(content tree)(left-child tree)

treetree

(and (= tmp 0) (not (lor? tree)))) tmp(eval-bool-tree (rest tree))

36

-eval-boolבסעיפים הבאים ננסה לקבל מימוש חליפי של השגרה tree ( תוך שמוש בזרמיםstreams .)

סופי או אינסופי, שכל , sשמקבלת זרם ( lor-stream sכתוב שגרה )הם או 0איבריו איברי 1 על זה אחר בזה לעבור השגרה על .

שערכו sהזרם איבר שימצא על 1עד כזה, איבר נמצא אם .הוא סופי וכל איבריו הם s. אם הזרם 1השגרה להחזיר את הערך

הוא אינסופי וכל s. )אם 0אפסים, על השגרה להחזיר את הערך לא יסתיים לעולם.(( lor-stream sאיבריו הם אפסים, חישוב )

(define (lor-stream s) (let ((x (stream-filter (lambda (x) (= x 1)) s))) (if (stream-null? x) 0 1)))

37

שהוזכרו בעצי-ביטויים לטיפול לשגרות שבנוסף עתה הנח ( השגרה גם לרשותך עומדת ( children-stream treeקודם,

הנח שעומדת . tree שאיבריו הם תתי-העצים של זרםשמחזירה שפועלת בדומה לשגרה ( land-stream sלרשותך גם שגרה בשם )

lor-stream -אך מחשבת את הland אל איברי הזרםs .

:eval-bool-treeהשלם את המימוש הבא של

(define (eval-bool-tree tree) (if (leaf? tree) _________________ ( (if (lor? tree) ______________ _______________) (stream-map _____________ ____________________ ) ) ) )

(content tree)lor-stream land-stream

eval-bool-tree (children-stream tree)