spring-2009

‫ת‪.‬ז‪.‬‬
‫עמוד ‪1‬‬
‫מס' מחברת‬
‫סמסטר ב' תשס"ט‪ ,‬מועד א'‬
‫יום שלישי‪ 7 ,‬ביולי ‪2009‬‬
‫בחינת סיום ‪ -‬מבוא מורחב למדעי המחשב‬
‫‪0368.1105‬‬
‫מרצים‪ :‬טובה מילוא ודניאל דויטש‬
‫מתרגלים‪ :‬אייל כהן ואלכסנדר אפראצין‬
‫הוראות כלליות‬
‫‪ .1‬משך הבחינה שלוש שעות‪.‬‬
‫‪ .2‬בבחינה ‪ 4‬שאלות‪ .‬יש לענות על כל השאלות‪.‬‬
‫‪ .3‬חומר עזר מותר בשימוש‪ :‬כל חומר כתוב או מודפס שהבאת אתך‪.‬‬
‫‪ .4‬יש לענות על כל השאלות‪ .‬משקלן אינו משקף בהכרח את הקושי והזמן הדרוש‬
‫לפתרונן‪.‬‬
‫‪ .5‬ניתן להשתמש בכל פונקציה שהוזכרה בשיעור או מופיעה בספר‪ .‬כמו כן מותר‬
‫להשתמש בפרוצדורות מסעיפים קודמים גם אם לא ענית על סעיפים אלו‪.‬‬
‫‪ .6‬כתוב את כל תשובותיך בטופס המבחן – המחברת לא תבדק!‬
‫‪ .7‬בשאלות בהן יש להשלים קוד בתבנית‪ ,‬אין לכתוב קוד אשר אינו תואם את התבנית‪.‬‬
‫אורך הקווים בתבנית אינו בהכרח רומז על ביטוי קצר או ארוך‪.‬‬
‫‪ .8‬יש לקרוא בעיון את השאלות‪.‬‬
‫‪ .9‬עזרו לבודק המבחן לבדוק את עבודתכם — כתבו בצורה נקיה ומסודרת‬
‫‪ .10‬הבחינה מכילה ‪ 19‬עמודים (כולל עמוד זה)‪.‬‬
‫בהצלחה!!‬
‫טבלה זו לשימוש הבודקים בלבד!!‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫סה"כ‬
‫ת‪.‬ז‪.‬‬
‫מס' מחברת‬
‫עמוד ‪2‬‬
‫שאלה ‪ 35( 1‬נק')‬
‫הערה‪ :‬כל ההתייחסויות בשאלה זו לסיבוכיות מתייחסות לסיבוכיות זמן‬
‫כזכור‪ ,‬רשימה מקושרת רגילה היא מבנה נתונים הכולל איברים‪ ,‬כאשר כל איבר כולל‬
‫ערך ומצביע אל האיבר הבא ברשימה‪ .‬מבנה נתונים זה מאפשר להגיע בסיבוכיות זמן‬
‫)‪ O(1‬אל האיבר הראשון ברשימה‪ ,‬מאפשר לקבל מכל איבר את הערך השמור בו‪,‬‬
‫וגם מאפשר‪ ,‬בהינתן מצביע לאיבר כלשהו ברשימה‪ ,‬להגיע אל האיבר הבא ברשימה‬
‫בסיבוכיות )‪.O(1‬‬
‫בשאלה זו נגדיר מבנה נתונים חדש‪ ,‬בשם רשימה מקושרת כפולה)‪ ,(dllist‬שתאפשר‬
‫לנו בנוסף ליכולות של רשימה מקושרת רגילה‪ ,‬גם להגיע אל האיבר האחרון ב‪-‬‬
‫)‪ ,O(1‬וגם‪ ,‬בהינתן מצביע לאיבר כלשהו‪ ,‬להגיע אל האיבר הקודם לו ב‪.O(1) -‬‬
‫כלומר‪ ,‬מבנה הנתונים החדש תומך בפעולות הבאות (ממומשות בהמשך)‪ ,‬כולן‬
‫בסיבוכיות זמן )‪:O(1‬‬
‫)‪(make-dllist‬‬
‫מייצר רשימה מקושרת כפולה ריקה‬
‫)‪(dllist-head dll‬‬
‫מקבל רשימה מקושרת כפולה‪ ,‬ומחזיר מצביע אל האיבר הראשון בה‬
‫)‪(dllist-tail dll‬‬
‫מקבל רשימה מקושרת כפולה ומחזיר מצביע אל האיבר האחרון בה‬
‫(‪(make-elem val next prev‬‬
‫מקבל ערך ‪ ,val‬מצביע לאיבר ‪ next‬ומצביע לאיבר ‪ ,prev‬ומייצר איבר‬
‫חדש‪ ,‬שהערך שלו הוא ‪ ,val‬האיבר הבא לו הוא ‪ , next‬והאיבר הקודם לו הוא‬
‫‪.prev‬‬
‫(‪(dll-elem-value elem‬‬
‫מקבל מצביע לאיבר ברשימה ומחזיר את הערך השמור בו‬
‫)‪(dllist-elem-next elem‬‬
‫מקבל מצביע לאיבר ברשימה ומחזיר מצביע לאיבר הבא אחריו‬
‫)‪(dllist-elem-prev elem‬‬
‫מקבל מצביע לאיבר ברשימה‪ ,‬ומחזיר מצביע לאיבר הקודם לו‬
3 ‫עמוד‬
‫מס' מחברת‬
.‫ז‬.‫ת‬
(dllist-empty? dll)
‫ אחרת‬#f ,‫ אם היא ריקה‬#t ‫מקבל רשימה מקושרת כפולה ומחזיר‬
(dllist-insert-at-start! dll val)
.dll ‫ בתחילת הרשימה המקושרת הכפולה‬val ‫מכניס איבר שערכו‬
:‫נתון המימוש הבא לרשימה מקושרת כפולה‬
;Constructors
(define (make-dllist) (cons null null))
(define (make-elem val next prev) (list val next prev))
;Selectors:
(define (dllist-head dll) (car dll))
(define (dllist-tail dll) (cdr dll))
(define (dllist-elem-value elem) (car elem))
(define (dllist-elem-next elem) (cadr elem))
(define (dllist-elem-prev elem) (caddr elem))
;Predicate:
(define (dllist-empty? dll) (null? (car dll)))
;Mutator:
(define (dllist-insert-at-start! dll val)
(let ((new_elem (make-elem
val
(dllist-head dll)
null)))
(cond ((dllist-empty? dll)
(begin
(set-car! dll new_elem)
(set-cdr! dll new_elem)))
(else
(begin
(set-car! (cddr (dllist-head dll)) new_elem)
(set-car! dll new_elem)
)))))
‫ת‪.‬ז‪.‬‬
‫עמוד ‪4‬‬
‫מס' מחברת‬
‫א‪ )i( .‬ציירו במסגרת את המבנה (זוגות ומצביעים) אליו מצביע ‪ p‬לאחר‬
‫סיום שערוך הביטויים הבאים‪:‬‬
‫))‪(define p (make-dllist‬‬
‫)‪(dllist-insert-at-start! p 1‬‬
‫)‪(dllist-insert-at-start! p 2‬‬
‫)‪(dllist-insert-at-start! p 3‬‬
‫(‪ )ii‬מה יציג המשערך כתוצאה משערוך הביטויים הבאים‪,‬‬
‫(לאחר שכבר שערך את הביטויים שבסעיף (‪ )i‬לעיל)?‬
‫)))‪(dllist-elem-value (dllist-elem-next (dllist-head p‬‬
‫)))‪(dllist-elem-value (dllist-elem-prev (dllist-tail p‬‬
‫_________________________________________________‬
‫_________________________________________________‬
‫הערה – בסעיפים ב' – ד' מותר לכם להשתמש בפונק' הממשק שהוגדרו לעיל‪.‬‬
‫ת‪.‬ז‪.‬‬
‫מס' מחברת‬
‫עמוד ‪5‬‬
‫ב‪ .‬כתבו בעמ' הבא פונקציה )‪ (list->dllist lst‬שמקבלת מצביע לרשימה‬
‫מקושרת רגילה‪ ,‬שכל איבריה מספריים‪ ,‬ומחזירה מצביע לרשימה מקושרת‬
‫כפולה עם אותם ערכים‪ ,‬באותו סדר‪.‬‬
‫)‪(define (list->dllist lst‬‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫)__________________________________________________‬
‫ג‪ )1( .‬כתבו פונקציה אשר מקבלת מצביע ‪ DL‬לרשימה מקושרת כפולה‪ ,‬שניתן‬
‫להניח שכל ערכיה הם סימבולים‪ ,‬ומסירה )תוך שימוש ב‪)mutation -‬‬
‫כפילויות‪ ,‬כדלהלן‪ :‬בכל פעם שסימבול מופיע יותר מפעם אחת ברשימה‪,‬‬
‫הפונקציה מסירה את כל המופעים שלו פרט לאחרון שבהם‪.‬‬
‫)‪(define (dllist-delete-dup! DL‬‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫ת‪.‬ז‪.‬‬
‫עמוד ‪6‬‬
‫מס' מחברת‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫______________________________________________________‬
‫)______________________________________________________‬
‫(‪ )2‬מהי סיבוכיות זמן הריצה של הפונקציה !‪ ,dllist-delete-dup‬כאשר ‪ n‬מסמן‬
‫את אורך הרשימה?‬
‫_________________________________________________‬
‫ד‪ .‬כתבו פונקציה אשר מקבלת סימבול ‪ ,sym‬ומצביע ‪ DL‬לרשימה מקושרת‬
‫כפולה‪ ,‬שניתן להניח שכל ערכיה הם סימבולים או מצביעים לרשימות‬
‫מקושרות כפולות (שערכיהן הם גם כן‪ ,‬סימבולים או מצביעים לרשימות‬
‫מקושרות כפולות וכן הלאה)‪ .‬הפונקציה מחזירה רשימה מקושרת כפולה‬
‫חדשה‪ ,‬שנראית כמו ‪ DL‬פרט לכך שכל איבר מ‪ DL -‬שערכו הוא ‪ sym‬הוסר‬
‫ממנה‪ .‬הרשימה המוחזרת היא חדשה‪ ,‬במובן זה ששום שינוי ברשימה המקורית‬
‫לא משנה את הרשימה החדשה ולהיפך‪.‬‬
‫)‪(define (dllist-delete-sym DL sym‬‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
‫________________________________________________________‬
7 ‫עמוד‬
‫מס' מחברת‬
.‫ז‬.‫ת‬
________________________________________________________
________________________________________________________
________________________________________________________
________________________________________________________)
)'‫ נק‬20( 2 ‫שאלה‬
.‫ציירו (בעמוד הבא) את מהלך השערוך של הביטויים הבאים במודל הסביבות‬
?‫מה יוצג על גבי המסך כתוצאה משערוך הביטויים‬
___________________________________________________________
___________________________________________________________
___________________________________________________________
___________________________________________________________
___________________________________________________________
(define (f res1 res2 counter)
(define (g)
(set! res2 (list res2 res2))
(set-cdr! res1 res2)
) ;end of g
(g)
(display (car res1))
(newline)
(display res2)
(newline)
(if (= counter 0) g
(f res1 res2 (- counter 1)))
) ;end of f
(define p '(6))
(define x 6)
(define tmp (f p x 1))
‫ת‪.‬ז‪.‬‬
‫מס' מחברת‬
‫עמוד ‪8‬‬
‫הערות‪:‬‬
‫‪ .1‬הקפידו למספר את הסביבות שנוצרות לפי סדר פתיחתן‪.‬‬
‫‪ .2‬הקריאות ל‪ newline ,display -‬לא יוצרות סביבה חדשה‬
‫‪ .3‬יש לצייר גם את מבני הרשימות והזוגות הנוצרים במהלך הריצה‬
‫‪GE‬‬
‫>‪<...‬‬
‫ת‪.‬ז‪.‬‬
‫מס' מחברת‬
‫עמוד ‪9‬‬
‫שאלה ‪ 25( 3‬נק')‬
‫שאלה זו עוסקת בזרמים (‪.)streams‬‬
‫א‪ .‬השלימו את הקוד של פונקצית ?‪ in-sorted‬המקבלת מספר וזרם (‪)stream‬‬
‫אינסופי של מספרים ממוינים בסדר עולה‪ .‬הפונקציה מחזירה ‪ #t‬אם המספר שהיא‬
‫מקבלת נמצא בתוך ה‪ stream-‬ו‪ #f -‬אחרת‪.‬‬
‫לדוגמא‪ (in-sorted 13 fibs) :‬צריך להחזיר ‪ #t‬כי ‪ 13‬הינו מספר פיבונצ'י‬
‫)‪ (in-sorted 14 stream-of-fibs‬צריך להחזיר ‪ #f‬כי ‪ 14‬איננו מספר פיבונצ'י‪.‬‬
‫)‪(define (in-sorted? x s‬‬
‫_____________________________________________‬
‫_____________________________________________‬
‫_____________________________________________‬
‫_____________________________________________‬
‫_____________________________________________‬
‫_____________________________________________‬
‫_____________________________________________‬
‫)‬
‫ב‪ .‬נגדיר קונבולוציה בין רשימת המספרים )‪ (a1 a2 .. an‬וזרם (‪ )stream‬אינסופי‬
‫של מספרים ]… ‪ [b1 b2 b3‬להיות זרם אינסופי של מספרים ] … ‪ [c1 c2 c3‬כך‬
‫ש‪. ci= a1*bi+a2*bi+1 ... an*bi+n -‬‬
‫לדוגמא‪ (stream-conv ‘(1 2) fibs) :‬צריך להחזיר‬
‫]……‪[2 3 5 8 13 21 34 55 89‬‬
‫השלימו את הקוד של פונקצית ‪ ,stream-conv‬המחשבת קונבולוציה כפי שהוגדרה‪.‬‬
‫ת‪.‬ז‪.‬‬
‫עמוד ‪10‬‬
‫מס' מחברת‬
‫)‪(define (stream-conv lst str‬‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫___________________________________‬
‫)___________________________________‬
‫שימו לב‪ :‬סעיף ג' בעמוד הבא‬
11 ‫עמוד‬
‫מס' מחברת‬
.‫ז‬.‫ת‬
?‫ אחרי שיערוך של ההגדרות שלהלן‬x2 -‫ ו‬x1 ‫ מה יהיו הערכים של‬.‫ג‬
X1=________________
(define x1 0)
(define x2 0)
(define str1
(cons-stream 1
(begin (set! x1 (+ x1 1)) str1)
))
(define (integers n)
(cons-stream n
(begin (set! x2 (+ x2 1))
(integers (+ n 1))
)))
(define str2 (integers 1))
(define c1 (stream-conv '(1 1) str1))
(define c2 (stream-conv '(1 1) str2))
X2=__________
‫ת‪.‬ז‪.‬‬
‫עמוד ‪12‬‬
‫מס' מחברת‬
‫שאלה ‪ 20( 4‬נק')‬
‫בשאלה זו נרחיב את המשערך המטא‪-‬מעגלי ‪ mc-eval‬כך שיתמוך בביטוי ‪special form‬‬
‫מהצורה‬
‫)‪.(loop init cond update body‬‬
‫‪ loop‬היא פקודה חדשה וכל אחד מארבעת הביטויים שאחריה עשוי להיות כל ביטוי‪.‬‬
‫המשמעות של ביטוי זה‪:‬‬
‫(‪ )1‬שערך את ביטוי ה‪ init -‬פעם אחת‬
‫(‪ )2‬שערך את ביטוי ה‪ .cond -‬אם ערכו שונה מ‪ ,#t -‬סיים את השערוך‬
‫(‪ )3‬אם ערכו של ביטוי ה‪ cond -‬הוא ‪ ,#t‬שערך את ‪ body‬ואז שערך את ‪,update‬‬
‫וחזור לשלב ‪ 2‬להמשך שערוך‬
‫הערך שמוחזר בסיום השערוך הוא הערך של השערוך האחרון של ‪ .body‬אם ‪body‬‬
‫לא שוערך כלל‪ ,‬יוחזר הסימבול ‪'OK‬‬
‫לדוגמא‪:‬‬
‫)‪(loop (define x 0‬‬
‫)‪(< x 3‬‬
‫))‪(set! x (+ x 1‬‬
‫))‪(display x‬‬
‫ידפיס את המספרים ‪ .0 1 2‬זאת מכיוון שקודם ישוערך )‪ (define x 0‬פעם אחת‪ ,‬ואז‬
‫ישוערך התנאי )‪ (< x 3‬שיחזיר ‪ .#t‬לכן ישוערך )‪ ,(display x‬שידפיס ‪ ,0‬ואז‬
‫( )‪ (set! x (+ x 1‬שיעדכן את ערכו של ‪ x‬להיות ‪ .1‬אז שוב ישוערכו התנאי‪ ,‬ההדפסה‬
‫ופעולת ההשמה (בסדר הזה)‪ ,‬וחוזר חלילה‪ ,‬עד אשר ערכו של ‪ x‬יהיה ‪ ,3‬התנאי לא‬
‫יתקיים ושערוך הביטוי יסתיים‪.‬‬
‫א‪ .‬השלם את ההגדרות הבאות‪:‬‬
‫‪;predicate‬‬
‫)__________________________________________ )‪(define (loop? exp‬‬
‫‪;selectors‬‬
‫)_______________________________________ )‪(define (loop-init exp‬‬
‫ת‪.‬ז‪.‬‬
‫עמוד ‪13‬‬
‫מס' מחברת‬
‫)______________________________________ )‪(define (loop-cond exp‬‬
‫)____________________________________ )‪(define (loop-update exp‬‬
‫)_____________________________________ )‪(define (loop-body exp‬‬
‫ב‪ .‬השלימו את מימוש הפונקציה ‪ eval-loop‬המשערך ביטוי מסוג ‪loop‬‬
‫)‪(define (eval-loop exp env‬‬
‫))_________________ ‪(let ((tmp‬‬
‫)‪(define (help-eval-loop‬‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫__________________________________________________‬
‫)__________________________________________________‬
‫____________________________________________________‬
‫____________________________________________________‬
‫____________________________________________________‬
‫____________________________________________________‬
‫))__________________________________________________‬
‫ג‪ .‬כעת נותר להוסיף שורת קוד נוספת לפונקציה ‪ mc-eval‬כדי לתמוך בפקודת ‪.loop‬‬
‫מהי השורה והיכן תוסיפו אותה?‬
‫שורת הקוד הנוספת‪:‬‬
‫________________________________________________________‬
‫היכן‪ ,‬בתוך הפונקציה‪ ,‬תוסיפו את שורה זו?‬
‫________________________________________________________‬
‫________________________________________________________‬
‫ת‪.‬ז‪.‬‬
‫מס' מחברת‬
‫עמוד ‪14‬‬
15 ‫עמוד‬
‫מס' מחברת‬
Running loop:
(define input-prompt ";;; M-Eval input:")
(define output-prompt ";;; M-Eval value:")
(define (driver-loop)
(prompt-for-input input-prompt)
(let ((input (read)))
(let ((output (mc-eval input the-global-environment)))
(cond ((eq? output exit-object)
'done)
(else
(announce-output output-prompt)
(user-print output)
(driver-loop))))))
(define (prompt-for-input string)
(newline) (newline) (display string) (newline))
(define (announce-output string)
(newline) (display string) (newline))
(define exit-object (cons nil nil))
(define (exit-driver) exit-object)
(define (user-print object)
(if (compound-procedure? object)
(display (list 'compound-procedure
(procedure-parameters object)
(procedure-body object)
'<procedure-env>))
(display object)))
Eval:
(define (mc-eval exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((quoted? exp) (text-of-quotation exp))
((assignment? exp) (eval-assignment exp env))
((definition? exp) (eval-definition exp env))
((if? exp) (eval-if exp env))
((lambda? exp)
(make-procedure (lambda-parameters exp)
(lambda-body exp)
env))
((begin? exp)
(eval-sequence (begin-actions exp) env))
((cond? exp) (mc-eval (cond->if exp) env))
((application? exp)
(mc-apply (mc-eval (operator exp) env)
(list-of-values (operands exp) env)))
(else
(error "Unknown expression type -- MC-EVAL" exp))))
(define (eval-sequence exps env)
(cond ((last-exp? exps) (mc-eval (first-exp exps) env))
(else (mc-eval (first-exp exps) env)
(eval-sequence (rest-exps exps) env))))
(define (last-exp? seq) (null? (cdr seq)))
(define (first-exp seq) (car seq))
.‫ז‬.‫ת‬
16 ‫עמוד‬
‫מס' מחברת‬
(define (rest-exps seq) (cdr seq))
Apply:
(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)
arguments
(procedure-environment procedure))))
(else
(error
"Unknown procedure type -- MC-APPLY" procedure))))
(define (primitive-procedure? proc)
(tagged-list? proc 'primitive))
(define (apply-primitive-procedure proc args)
(apply-in-underlying-scheme
(primitive-implementation proc) args))
(define apply-in-underlying-scheme apply)
(define (compound-procedure? p)
(tagged-list? p 'procedure))
(define (procedure-parameters p) (cadr p))
(define (procedure-body p) (caddr p))
(define (procedure-environment p) (cadddr p))
The Global Enviroment:
(define the-global-environment (setup-environment))
(define (setup-environment)
(let ((initial-env
(extend-environment (primitive-procedure-names)
(primitive-procedure-objects)
the-empty-environment)))
(define-variable! 'true true initial-env)
(define-variable! 'false false initial-env)
initial-env))
(define primitive-procedures
(list (list 'car car)
(list 'cdr cdr)
(list 'cons cons) (list 'null? null?)
(list '+ +)
(list '- -)
(list '* *)
(list '/ /)
(list '= =)
(list 'print user-print)
(list 'exit exit-driver)
;;
more primitives
))
(define (primitive-procedure-names)
(map car
primitive-procedures))
(define (primitive-procedure-objects)
(map (lambda (proc) (list 'primitive (cadr proc)))
primitive-procedures))
.‫ז‬.‫ת‬
17 ‫עמוד‬
‫מס' מחברת‬
.‫ז‬.‫ת‬
(define (primitive-implementation proc) (cadr proc))
(define the-empty-environment '())
(define (extend-environment vars vals base-env)
(if (= (length vars) (length vals))
(cons (make-frame vars vals) base-env)
(if (< (length vars) (length vals))
(error "Too many arguments supplied" vars vals)
(error "Too few arguments supplied" vars vals))))
(define (make-frame variables values)
(cons variables values))
(define (frame-variables frame) (car frame))
(define (frame-values frame) (cdr frame))
Self evaluating: ((self-evaluating? exp) exp)
(define (self-evaluating? exp)
(cond ((number? exp) true)
((string? exp) true)
(else false)))
Combination expression:
(operator exp) env)
((application? exp) (mc-apply (mc-eval
(list-ofvalues (operands exp) env)))
(define (application? exp) (pair? exp))
(define (operator exp) (car exp))
(define (operands exp) (cdr exp))
(define (list-of-values exps env)
(if (no-operands? exps)
'()
(cons (mc-eval (first-operand exps) env)
(list-of-values (rest-operands exps) env))))
(define (no-operands? ops) (null? ops))
(define (first-operand ops) (car ops))
(define (rest-operands ops) (cdr ops))
lambda expression:
parameters exp)
((lambda? exp) (make-procedure (lambda-
(lambda-body exp)
env))
(define (lambda? exp)(tagged-list? exp 'lambda))
(define (lambda-parameters exp) (cadr exp))
(define (lambda-body exp) (cddr exp))
(define (make-procedure parameters body env)
(list 'procedure parameters body env))
quote expression: ((quoted? exp) (text-of-quotation exp))
(define (quoted? exp)
(tagged-list? exp 'quote))
(define (text-of-quotation exp) (cadr exp))
if expression: ((if? exp) (eval-if exp env))
(define (if? exp) (tagged-list? exp 'if))
(define (eval-if exp env)
18 ‫עמוד‬
‫מס' מחברת‬
(if (true? (mc-eval (if-predicate exp) env))
(mc-eval (if-consequent exp) env)
(mc-eval (if-alternative exp) env)))
(define (if-predicate exp) (cadr exp))
(define (if-consequent exp) (caddr exp))
(define (if-alternative exp)
(if (not (null? (cdddr exp)))
(cadddr exp)
'false))
begin expression:
env))
((begin? exp)(eval-sequence (begin-actions exp)
(define (begin? exp) (tagged-list? exp 'begin))
(define (begin-actions exp) (cdr exp))
(define (eval-sequence exps env)
(cond ((last-exp? exps) (mc-eval (first-exp exps) env))
(else (mc-eval (first-exp exps) env)
(eval-sequence (rest-exps exps) env))))
(define (last-exp? seq) (null? (cdr seq)))
(define (first-exp seq) (car seq))
(define (rest-exps seq) (cdr seq))
cond expression: ((cond? exp) (mc-eval (cond->if exp) env))
(define (cond? exp) (tagged-list? exp 'cond))
(define (cond->if exp)
(expand-clauses (cond-clauses exp)))
(define (cond-clauses exp) (cdr exp))
(define (expand-clauses clauses)
(if (null? clauses)
'false
; no else clause
(let ((first (car clauses))
(rest (cdr clauses)))
(if (cond-else-clause? first)
(if (null? rest)
(sequence->exp (cond-actions first))
(error "ELSE clause isn't last -- COND->IF"
clauses))
(make-if (cond-predicate first)
(sequence->exp (cond-actions first))
(expand-clauses rest))))))
(define (cond-else-clause? clause)
(eq? (cond-predicate clause) 'else))
(define (cond-predicate clause) (car clause))
(define (cond-actions clause) (cdr clause))
(define (make-if predicate consequent alternative)
(list 'if predicate consequent alternative))
(define (sequence->exp seq)
(cond ((null? seq) seq)
((last-exp? seq) (first-exp seq))
(else (make-begin seq))))
.‫ז‬.‫ת‬
19 ‫עמוד‬
‫מס' מחברת‬
(define (last-exp? seq) (null? (cdr seq)))
(define (first-exp seq) (car seq))
(define (make-begin seq) (cons 'begin seq))
Variables: ((variable? exp) (lookup-variable-value exp env))
(define (variable? exp) (symbol? exp))
(define (lookup-variable-value var env)
(define (env-loop env)
(define (scan vars vals)
(cond ((null? vars)
(env-loop (enclosing-environment env)))
((eq? var (car vars))
(car vals))
(else (scan (cdr vars) (cdr vals)))))
(if (eq? env the-empty-environment)
(error "Unbound variable" var)
(let ((frame (first-frame env)))
(scan (frame-variables frame)
(frame-values frame)))))
(env-loop env))
(define (enclosing-environment env) (cdr env))
(define (first-frame env) (car env))
set! expression: ((assignment? exp) (eval-assignment exp env))
(define (assignment? exp)
(tagged-list? exp 'set!))
(define (eval-assignment exp env)
(set-variable-value! (assignment-variable exp)
(mc-eval (assignment-value exp) env)
env)
'ok)
(define (assignment-variable exp) (cadr exp))
(define (assignment-value exp) (caddr exp))
(define (set-variable-value! var val env)
(define (env-loop env)
(define (scan vars vals)
(cond ((null? vars)
(env-loop (enclosing-environment env)))
((eq? var (car vars))
(set-car! vals val))
(else (scan (cdr vars) (cdr vals)))))
(if (eq? env the-empty-environment)
(error "Unbound variable -- SET!" var)
(let ((frame (first-frame env)))
(scan (frame-variables frame)
(frame-values frame)))))
(env-loop env))
(define (enclosing-environment env) (cdr env))
(define (first-frame env) (car env))
define expression: ((definition? exp) (eval-definition exp env))
(define (definition? exp)
(tagged-list? exp 'define))
(define (eval-definition exp env)
.‫ז‬.‫ת‬
20 ‫עמוד‬
‫מס' מחברת‬
(define-variable! (definition-variable exp)
(mc-eval (definition-value exp) env)
env)
'ok)
(define (definition-variable exp)
(if (symbol? (cadr exp))
(cadr exp)
(caadr exp)))
(define (definition-value exp)
(if (symbol? (cadr exp))
(caddr exp)
(make-lambda (cdadr exp)
(cddr exp))))
(define (make-lambda parameters body)
(cons 'lambda (cons parameters body)))
(define (define-variable! var val env)
(let ((frame (first-frame env)))
(define (scan vars vals)
(cond ((null? vars)
(add-binding-to-frame! var val frame))
((eq? var (car vars))
(set-car! vals val))
(else (scan (cdr vars) (cdr vals)))))
(scan (frame-variables frame)
(frame-values frame))))
(define (add-binding-to-frame! var val frame)
(set-car! frame (cons var (car frame)))
(set-cdr! frame (cons val (cdr frame))))
other definitions:
(define (tagged-list? exp tag)
(if (pair? exp)
(eq? (car exp) tag)
false))
(define false #f)
(define true (not false))
(define (true? x) (not (eq? x false)))
(define (false? x) (eq? x false))
.‫ז‬.‫ת‬