Pregunta de novato en Common Lisp:
¿Cómo hacer que mi procedimiento devuelva un objeto procesal distinto con su propio enlace local cada vez que llame? Actualmente, uso let para crear el estado local, pero dos llamadas a funciones comparten el mismo estado local. Aquí está el código
(defun make-acc ()
(let ((balance 100))
(defun withdraw (amount)
(setf balance (- balance amount))
(print balance))
(defun deposit (amount)
(setf balance (+ balance amount))
(print balance))
(lambda (m)
(cond ((equal m 'withdraw)
(lambda (x) (withdraw x)))
((equal m 'deposit)
(lambda (x) (deposit x)))))))
;; test
(setf peter-acc (make-acc))
(setf paul-acc (make-acc))
(funcall (funcall peter-acc 'withdraw) 10)
;; Give 90
(funcall (funcall paul-acc 'withdraw) 10)
;; Expect 90 but give 80
¿Debería hacerlo de otra manera? ¿Está mal mi forma de escribir? ¿Alguien puede ayudarme a aclarar esta duda? Gracias por adelantado.
lisp
common-lisp
state
let
netherwave
fuente
fuente
Respuestas:
Tenga en cuenta que, incluso después
defun
de que se aborde el problema -is-global, necesita mucha menos maquinaria de la que necesita para hacer algo como esto. Por ejemplo:Entonces
Obviamente
account-operation
es solo una conveniencia.fuente
Tal vez quieres orientación a los objetos?
Uso:
Podemos crear cuentas con otro saldo:
Para más información, sugiero el Cookbook: https://lispcookbook.github.io/cl-cookbook/clos.html
fuente
Una regla general es que
defun
debe usarse solo cuando se define una función en el nivel superior. Para definir las funciones locales de los dos operadores especialesflet
ylabels
puede ser usado ( manual de ).Por ejemplo:
labels
es comoflet
, pero se usa cuando hay definiciones recursivas.Entonces no necesita devolver funciones dentro de la función devuelta por
make-acc
, pero en él simplemente puede ejecutar la operación requerida:La llamada será más simple y devolverá el valor esperado:
Finalmente, si lo desea, también puede devolver dos funciones diferentes para realizar depósitos y retiros en la cuenta:
usando esto por ejemplo como:
fuente
El único problema serio aquí es
defun
que en común lisp no se usa para definir funciones locales.Por ejemplo, podría usar
lambda
s para esas operaciones, especialmente porque desea devolver lambdas ...Tenga en cuenta que usé en
let*
lugar delet
porque necesita poder verbalance
en los dos enlaces siguientes.fuente