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