Search code examples
schemelispcommon-lispsbclmit-scheme

Convert MIT Scheme code logic into Common Lisp


In one of my books i have this scheme code and want to convert it to Common Lisp:

(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)

then i'll create it with :

(define acc (make-account 1500))

and then call deposit or withdraw with :

((acc 'withdraw) 50) or

((acc 'deposit) 75)

As far as I understand acc gets replaced with the function dispatch and returns either withdraw or deposit and then evaluates the expression for example: ((acc 'withdraw) 50) -> ((dispatch 'withdraw) 50) -> (withdraw 50)

Now, how do i convert this programm and logic to Common Lisp. I appreciate your help.


Solution

  • The basic structure is the same, but you use FLET or LABELS to define local functions within a function. In this case you need to use LABELS because the functions refer to each other.

    In Common Lisp you have to use FUNCALL to call functions dynamically. This makes this style of functional programming inconvenient; Common Lisp programmers generally use DEFSTRUCT or CLOS.

    (defun make-account (balance)
      (labels
       ((withdraw (amount)
          (if (>= balance amount)
              (decf balance amount)
            (error "Insufficient funds")))
        (deposit (amount)
          (incf balance amount))
        (dispatch (m)
          (cond
           ((eq m 'withdraw) #'withdraw)
           ((eq m 'deposit) #'deposit)
           (t (error "Unknown request -- MAKE-ACCOUNT ~s" m))))))
      #'dispatch)
    
    (defvar acc (make-account 1500))
    (funcall (funcall acc 'withdraw) 50)
    (funcall (funcall acc 'deposit) 75)