Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- #|
- An environment is a sequence of frames, and a frame is a table of bindings.
- Bindings assign values to variables. Every expression is evaluated with
- respect to some environment. The value of a variable is obtained from the
- first frame in the environment containing the variable.
- A procedure object is a pair consisting of code and an environment. The code
- consists of the formal parameters and the function body. The environment is
- the environment of definition, also called the enclosing environment.
- When you call a function, you first create a new frame below the enclosing
- environment and bind the formal parameters to the passed values in this frame.
- Then the body of the function is evaluated in this new binding environment.
- |#
- ;;;;;;;;;
- ;; 3.9 ;;
- ;;;;;;;;;
- #|
- Every time we call a function, the body of the function is evaluated in the
- binding environment. So calling a recursive function will create an
- environment structure consisting of several parallel binding frames, one for
- each call, all just below the enclosing environment. In particular, you do not
- get a descending chain of binding frames; that only happens when you have
- local definitions.
- The evaluation of recursive factorial applied to 6, will create an environment
- structure consisting of six parallel binding frames. In the first binding
- frame, n is bound to 6. In the second, n is bound to 5, and so on, until, in
- the last binding frame, n is bound to 1. When n is 1, the body of factorial
- can be evaluated without making any more recursive calls, so this is the last
- frame created.
- The evaluation of iterative factorial applied to 6, will call factorial once
- and fact-iter seven times. So that function call will create an environment
- structure consisting of eight parallel binding frames, one for factorial where
- n is bound to 6, and seven for fact-iter where product, counter, and max-count
- are bound to their appropriate values.
- |#
- ;;;;;;;;;;
- ;; 3.10 ;;
- ;;;;;;;;;;
- ;; Describe the environment structure for:
- (define (make-withdraw initial-amount)
- (let ([balance initial-amount])
- (lambda (amount)
- (cond [(>= balance amount)
- (set! balance (- balance amount))
- balance]
- [else "Insufficient funds"]))))
- #|
- Note that the let form is syntactic sugar for:
- (define (make-withdraw initial-amount)
- ((lambda (balance)
- (lambda (amount)
- (cond [(>= balance amount)
- (set! balance amount)
- balance]
- [else "Insufficient funds"])))
- initial-amount))
- |#
- (define W1 (make-withdraw 100))
- #|
- W1 is created in the global environment. Its value is the result of calling
- the outer lambda, the function of balance, on initial-amount. This value will
- be the inner lambda, the function of amount.
- So to evaluate W1, we first create a binding frame E1 below the global
- environment, where we bind balance to initial-amount and define the inner
- lambda, the function of amount. The enclosing environment for the inner lambda
- is the binding environment for the outer lambda.
- |#
- (W1 50)
- ;; 50
- #|
- Calling W1, whose value is the inner lambda, on 50, creates a new binding frame
- below E1, where amount is bound to 50, and the body of the inner lambda is
- evaluated.
- |#
- (define W2 (make-withdraw 100))
- #|
- If we call make-withdraw again to create another account W2, W2 will also be
- created in the global environment, and its value will also be the identical
- inner lambda, the function of amount. However, this time, the enclosing
- environment for the inner lambda will not be E1, but rather the new binding
- frame for the second call, which will be parallel to E1.
- |#
- (W2 10)
- ;; 90
- ;;;;;;;;;;
- ;; 3.11 ;;
- ;;;;;;;;;;
- ;; Describe the environment structure for:
- (define (make-account balance)
- (define (withdraw amount)
- (cond [(>= balance amount)
- (set! balance (- balance amount))
- balance]
- [else "Insufficient funds"]))
- (define (deposit amount)
- (set! balance (+ balance amount))
- balance)
- (define (dispatch m)
- (cond [(eq? m 'withdraw) withdraw]
- [(eq? m 'deposit) deposit]
- [else (error "Unknown request -- MAKE-ACCOUNT:" m)]))
- dispatch)
- (define acc (make-account 50))
- #|
- acc is defined in the global environment. Its value is the result of calling
- make-account on 50. Since make-account is defined in the global environment,
- calling make-account creates a binding frame E1, below the global environment,
- where balance is bound to 50 and the body of make-account is evaluated.
- Evaluating the body of make-account in E1 creates new functions withdraw,
- deposit, and dispatch, all of which have E1 as their enclosing environment.
- The value of acc is this dispatch function, the one defined inside E1.
- |#
- ((acc 'deposit) 40)
- ;; 90
- #|
- Calling acc on 'deposit returns the deposit function defined inside E1.
- Calling deposit on 40, creates a new binding frame, below E1, where amount is
- bound to 40, and the body of the deposit function is evaluated.
- |#
- ((acc 'withdraw) 60)
- ;; 30
- #|
- Similarly, calling acc on 'withdraw returns the withdraw function defined
- inside E1. Calling withdraw on 60, creates a new binding frame, below E1,
- where amount is bound to 60, and the body of the withdraw function is
- evaluated.
- |#
- (define acc2 (make-account 100))
- #|
- Calling make-account a second time creates a new binding frame E2, below the
- global environment, where balance is bound to 100, and functions withdraw,
- deposit, and dispatch are defined. These functions have the exact same code,
- formal parameters and body, as they do for acc, but their enclosing environment
- is E2, not E1.
- In particular, the local state for acc is kept in E1, while the local state for
- acc2 is kept in E2. The only part of the environment structure common to acc
- and acc2 is the global environment.
- |#
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement