wes
wes

Reputation: 5

Defining a function to call nested functions

I have been working through an online scheme tutorial and am confused about the following code:

(define make-bank-account
  (lambda (balance)
    (display "Ding")
    (lambda (n)
      (display "Dong")
      (set! balance (+ balance n))
      balance)))

(define account1 (make-bank-account 10))

;; My code
(define account2
  (lambda (x)
    ((make-bank-account 10) x)))

Why is it that account2 does not accumulate the balance from call to call, while account1 does? For example:

(account1 5)
-> Dong
;Value: 15

(account1 10)
-> Dong
;Value: 25

(account2 5)
-> DingDong
;Value: 15

(account2 10)
-> DingDong
;Value: 20

I have tested the code using "Ding" and "Dong" and noticed that when calling account1 "Ding" is never displayed while calling account2 both "Ding" and "Dong" are displayed. I believe this corresponds with the issue. Thanks in advance!

Upvotes: 0

Views: 991

Answers (2)

Diego Sevilla
Diego Sevilla

Reputation: 29011

In your code, you're creating a new function every time you call it, because the function you return includes a new call to make-bank-account. If you change it slightly to:

(define account2
    (lambda (x)
        (account1 x)))

obviously you would get the correct functoning. account1, however, calls the make-bank-account and uses the function returned, that "holds" the placeholder with the correct value when you call it repeatedly.

To show the difference, you can "remember" the account you created. This is essentially the same original code:

(define new-account
  (lambda (initial-amount)
    (define my-account (make-bank-account initial-amount))
    (lambda (amount)
      (my-account amount))))

Note how the function you return (the second lambda) already has initialized the my-account, with just one call to make-bank-account. Then, to create a new account:

> (define account3 (new-account 20))
Ding
> (account3 30)
Dong50
> (account3 30)
Dong80
> 

Upvotes: 1

molbdnilo
molbdnilo

Reputation: 66371

The amount doesn't accumulate because there's no account to accumulate into.

Looking at the definition,

(define account2
  (lambda (x)
    ((make-bank-account 10) x)))

account2 is a function that

  • Takes an amount x
  • Creates a new account with the balance 10
  • Deposits the given amount x into the newly created account

The account it creates is never stored anywhere, so nothing more can happen to it.

That is, every time you say (account2 5) – which is equivalent to ((make-bank-account 10) 5) – a new account is created (Ding), and 5 units deposited into that (Dong).

Upvotes: 1

Related Questions