(my-account 'balance)
(my-account 'withdraw 10) (my-account 'balance)
(my-account 'withdraw 10)We can also create objects that handle deposits as well as withdrawals, and thus we can represent simple bank accounts. Here is a procedure that returns a “bank-account object” with a specified initial balance:
(define (make-account balance)
(define (withdraw amount)
(if (>= balance amount)
(begin (set! balance
(- balance amount))
balance)
"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)
Each call to make-account sets up an environment with a local state variable balance. Within this environment, make-account defines procedures deposit and withdraw that access balance and an additional procedure dispatch that takes a “message” as input and returns one of the two local procedures. The dispatch procedure itself is returned as the value that represents the bank-account object. This is precisely the message-passing style of programming that we saw in 2.4.3, although here we are using it in conjunction with the ability to modify local variables.3.1.1 Local State Variables
https://sarabander.github.io/sicp/html/3_002e1.xhtml#g_t3_00...
Closures indeed! A key concept of Scheme that distinguished it from most Lisps at the time:
(LAMBDA ( <identifier list> ) <body> )
Lambda-expressions evaluate to procedures. Unlike most LISP systems, SCHEME does not consider a lambda-expression (an s-expression whose car is the atom LAMBDA) to be a procedure. A lambda-expression only evaluates to a procedure. A lambda-expression should be thought of as a partial description of a procedure; a procedure and a description of it are conceptually distinct objects. A lambda-expression must be “closed” (associated with an environment) to produce a procedure object. Evaluation of a lambda-expression performs such a closure operation.
The resulting procedure takes as many arguments as there are identifiers in the identifier list of the lambda-expression. When the procedure is eventually invoked, the intuitive effect is that the evaluation of the procedure call is equivalent to the evaluation of the <body> in an environment consisting of (a) the environment in which the lambda-expression had been evaluated to produce the procedure, plus (b) the pairing of the identifiers of the <identifier list> with the arguments supplied to the procedure. The pairings (b) take precedence over the environment (a), and to prevent confusion no identifier may appear twice in the <identifier list>. The net effect is to implement ALGOL-style lexical scoping [Naur], and to “solve the funarg problem” [Moses].
THE REVISED REPORT ON SCHEME: A DIALECT OF LISP
B.1. Kernel Magic Forms
https://research.scheme.org/lambda-papers/lambda-papers-revi...
Moar:
3.2 The Environment Model of Evaluation
https://sarabander.github.io/sicp/html/3_002e2.xhtml#g_t3_00...
Here's a video demo of the code completion in vscode: