תוכנה 1 בשפת Java תרגול מספר 8: הורשה אסף זריצקי ומתי שמרת בית הספר למדעי המחשב אוניברסיטת תל אביב.
מבוא מורחב למדעי המחשב בשפת Scheme
description
Transcript of מבוא מורחב למדעי המחשב בשפת Scheme
מבוא מורחב למדעי המחשב Scheme בשפת
13תרגול
Metacircular Evaluator
4.1, pages 362-398
definitions file on web
2
Overview
1. Eval, apply
2. Change definition
3. Add let, let*
4. Add special forms and, or
5. Abstraction of frame scanning
3
4
Evaluator: a program that
determines meaning of expressions
in a programming language.
Metacircular: written in the same language that it evaluates
Read-Eval-Print Loop
(define (driver-loop)1. PRINT PROMPT (prompt-for-input input-prompt)2. READ INPUT EXPRESSION (let ((input (read))) 3. EVALUATE EXPRESSION (let ((output (mc-eval input the-global-environment)))
…4. PRINT RESULT (user-print output)5. LOOP (driver-loop))))))
5
Eval-Apply
Mutual recursion between eval and apply
To evaluate a compound expression means to evaluate the sub-expressions recursively, then apply the operator to the arguments.
To apply a function to arguments means to evaluate the body of the function in a new environment.
6
Eval
Evaluate expression in given environment
(define (mc-eval exp env) (cond ((self-evaluating? exp) exp)… ((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env)))
The name mc-eval is used to differ from the primitive eval
7
Apply
Apply procedure to list of arguments
(define (mc-apply procedure arguments)…(eval-sequence (procedure-body procedure) (extend-environment (procedure-parameters procedure) arguments (procedure-environment procedure))))
The name mc-apply is used to differ from the primitive apply
8
Change definition
from (define x 7)
to (x := 7)
and
from (define (square x) (* x x))
to ((square x) := (* x x))
9
Change eval case
from:(define (definition? exp) (tagged-list? exp 'define))
(define (tagged-list? exp tag) (if (pair? exp) (eq? (car exp) tag) false))to:(define (definition? exp) (and (pair? exp) (pair? (cdr exp)) (eq? (cadr exp) ':=)))
10
Change selectors
(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))))
(car(car
(car
(caar
(cdar
11
Adding let, let*
Rearranging as another expression
12
let
(let ((<var1> <exp1>) … (<varn> <expn>)) <body>)
is equivalent to
((lambda (<var1> … <varn>) <body>) <exp1> … <expn>)
add a syntactic transformationlet->combination
13
let - case in eval
((let? exp)
(mc-eval (let->combination exp) env))
(define (let? exp)
(tagged-list? exp ‘let))
let - predicate
14
let - constructors
(define (make-combination
function expressions)
(cons function expressions))
15
let - selectors
(define (let-bindings exp) (cadr exp))
(define (let-body exp) (cddr exp))
(define (let-variables exp) (map car (let-bindings exp)))
(define (let-expressions exp) (map cadr (let-bindings exp)))
16
let - evaluation
(define (let->combination exp)
(make-combination
(make-lambda
(let-variables exp)
(let-body exp))
(let-expressions exp)))
17
let*
The bindings of are performed sequentially.
Each binding is made in an environment inwhich all of the preceding bindings arevisible.
(let* ((x 3) (y (+ x 2)) (z (+ x y 5))) (* x z))> 39
18
let*
(let* ((<var1> <exp1>)…(<varn> <expn>))
<body>)
is equivalent to
(let ((<var1> <exp1>)) (let* ((<var2> <exp2>)… (<varn> <expn>)) <body>))
add a syntactic transformationlet*->nested-let
19
let* - example(let* ((<var1> <exp1>) (<var2> <exp2>)) <body>)=(let ((<var1> <exp1>)) (let* (<var2> <exp2>)) <body>))=(let ((<var1> <exp1>)) (let ((<var2> <exp2>)) (let* () <body>)))=(let ((<var1> <exp1>)) (let ((<var2> <exp2>)) (let () <body>)))
20
let* - case in eval
((let*? exp)
(mc-eval (let*->nested-let exp) env))
21
let* - constructors
(define (make-let bindings body)
(cons ‘let (cons bindings body)))
(define (make-let* bindings body)
(cons ‘let* (cons bindings body)))
22
let* - predicates
(define (let*? exp)
(tagged-list exp ‘let*))
(define (no-bindings? bindings)
(null? bindings))
23
let* - selectors
(define (let*-bindings exp) (cadr exp))
(define (let*-body exp) (cddr exp))
(define (let*-first-binding bindings)
(car bindings))
(define (let*-rest-bindings bindings)
(cdr bindings))
24
let* - evaluation
(define (let*->nested-let exp)
(if (no-bindings? (let*-bindings exp))
(make-let
(let*-bindings exp)
(let*-body exp))
(make-let
(list (let*-first-binding
(let*-bindings exp)) ; ((v1 e1))
(make-let*
(let*-rest-bindings (let*-bindings exp))
(let*-body exp))))
25
Special forms: and, or
Direct evaluation
26
and, or - cases in eval
(define (mc-eval exp env) (cond ((self-evaluating? exp) exp)…((and? exp) (eval-and (and-exps exp) env))((or? exp) (eval-or (or-exps exp) env))
((application? exp) (mc-apply (mc-eval (operator exp) env) (list-of-values (operands exp) env)))
27
and, or - predicates
(define (and? exp) (tagged-list? exp ‘and))
(define (or? exp) (tagged-list? exp ‘or))
(define (no-exps? exps) (null? exps))
(define (last-exp? exps) (null? (cdr exps)))
28
and, or - selectors
(define (and-exps exp) (cdr exp))
(define (or-exps exp) (cdr exp))
(define (first-exp exps) (car exps))
(define (rest-exps exps) (cdr exps))
29
and - evaluation
from left to right
Evaluation Return value
Any expression evaluates to false
false
All expressions evaluate to true
value of last expression
No expressions true
and - evaluation
(define (eval-and exps env) (if (no-exps? exps) true (let ((first (mc-eval (first-exp exps) env)))
(if (false? first) false (if (last-exp? exps) first (eval-and (rest-exps exps) env)))))
31
or - evaluation
from left to right
32
Evaluation Return value
Any expression evaluates to true
value of last expression
All expressions evaluate to false
false
No expressions false
or - evaluation
(define (eval-or exps env) (if (no-exps? exps) false (let ((first (mc-eval (first-exp exps) env)))
(if (true? first) first ;(if (last-exp? exps) false (eval-or (rest-exps exps) env)))))
33
Abstraction of frame scanning
Exercise 4.12
34
35
Frames
A frame is a set of bindings, represented as a pair of two lists: variables and values
Constructor(make-frame variables values)Selectors(frame-variables frame)(frame-values frame)Mutator(add-binding-to-frame! var val frame)
36
EnvironmentsAn environment consists of its first frame and an enclosing
environment
Constructor(extend-environment vars vals base-env)Selectors (first-frame env)(enclosing-environment env)Predefined environmentsthe-global-environmentthe-empty-environment
37
Frame Scanning
Performed by:• lookup-variable-value
invoked when evaluating names• set-variable-value!
invoked when evaluating set! expressions• define-value!
invoked when evaluating definitions
38
lookup-variable-value(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))
39
set-variable-value!(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))
40
define-variable!(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))))
41
All procedures are alike!
• Scan the frame for the variable’s name– If found, success operation
(return value / set value)– If not in frame, failure operation
(continue to next frame / add binding)
• Error on empty environment (if this can happen)
• We can get better abstraction– Capturing common patterns– Hiding frame scanning / mutation
42
Generic frame scan
(define (scan-first-frame var env succeed fail)
(define (scan vars vals)
(cond ((null? vars)
(fail))
((eq? var (car vars))
(succeed 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)))))
43
lookup-variable-value
(define (lookup-variable-value var env)
(define (succeed vals)
(get-binding-value vals))
(define (fail)
(scan-first-frame
var (enclosing-environment env) succeed fail))
(scan-first-frame var env succeed fail))
(define (get-binding-value vals)
(car vals))
44
set-variable-value!
(define (set-variable-value! var val env)
(define (succeed vals)
(set-binding-value! vals val))
(define (fail)
(scan-first-frame
var (enclosing-environment env) succeed fail))
(scan-first-frame var env succeed fail))
(define (set-binding-value! vals val)
(set-car! vals val))
45
define-variable!
(define (define-variable! var val env)
(define (succeed vals)
(set-binding-value! vals val))
(define (fail)
(add-binding-to-frame! var val (first-frame env))) (scan-first-frame var env succeed fail))