musthero
musthero

Reputation: 1288

Why in SICP one can see seemingly useless evaluation of local variable expressions? Different Scheme implementations behave differently

The deposit and withdraw procedures in the make-account code from SICP both have seemingly useless balance variable expression to evaluate,

  1. What is the practical purpose for doing that? (To me it seems redundant peace of code, but I don't think Abelson and Sussman would put something useless).

  2. Meanwhile, in DrRacket [run from IDE], the balance from withdraw gets printed, whereas the balance from deposit does not. Why is that? Is it a DrRacket's thing, a bug, or what.

  3. In Chicken Scheme and MIT Scheme [run from command line], the balance is not printed consistently for both deposit and withdraw.

The code is below. I just added (display "deposit:\n") and (display "withdraw:\n") to the original code for convenience. The balance variable expression in question is right after the display expressions, on the same line of code.

#lang racket

(define (make-account balance)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               (display "withdraw:\n") balance)
        "Insufficient funds"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    (display "deposit:\n") balance)
  (define (dispatch m)
    (cond ((eq? m 'deposit) deposit)
          ((eq? m 'withdraw) withdraw)
          ((eq? m 'balance) balance)
          (else
           (error "Unknown request: MAKE-ACCOUNT" m))))
  dispatch)

(define (exchange account1 account2)
  (let ((difference (- (account1 'balance)
                       (account2 'balance))))
    ((account1 'withdraw) difference)
    ((account2 'deposit) difference)))


(define a1 (make-account 100))
(define a2 (make-account 75))

(exchange a1 a2)

E.g., here is the output from Dr.Racket,

withdraw:
deposit:
100

withdraw prints nothing, deposit prints '100'. Why not to print either both or none?

Upvotes: 0

Views: 108

Answers (2)

Peter Winton
Peter Winton

Reputation: 796

  • withdraw: is printed as the side effect of (display "withdraw:\n")
  • deposit: is printed as the side effect of (display "deposit:\n")
  • 100 is printed as the return value of (exchange a1 a2)

Variations in behavior between Scheme implementations and IDE vs. REPL may be explained by:

  • whether the five top-level expressions in your program are evaluated one by one or as if wrapped in an implicit begin
  • the fact that define, set!, and display have unspecified return values, so an implementation can return whatever it wants (it might even be different from run to run depending on optimization details)

Upvotes: 1

jcubic
jcubic

Reputation: 66610

It's not useless balance is the closure return value. It's not used in this code but may be useful:

(define a3 (make-account 100))
(display (string-append "balance: "
                        (number->string ((a3 'deposit) 10))
                        "\n"))
;; ==> deposit:
;; ==> balance: 110

The value will also be printed if you execute in REPL:

> (define a4 (make-account 100))
> ((a4 'deposit) 10)
;; ==> deposit:
;; ==> 110

This code will behave the same in every Scheme.

Upvotes: 1

Related Questions