Neuling Frage in Common Lisp:
Wie kann ich meine Prozedur so gestalten, dass bei jedem Aufruf ein bestimmtes prozedurales Objekt mit einer eigenen lokalen Bindung zurückgegeben wird? Derzeit verwende ich let, um den lokalen Status zu erstellen, aber zwei Funktionsaufrufe verwenden denselben lokalen Status. Hier ist der Code,
(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
Soll ich es anders machen? Ist meine Schreibweise falsch? Kann mir bitte jemand helfen, diesen Zweifel auszuräumen? Danke im Voraus.
lisp
common-lisp
state
let
Unterwelle
quelle
quelle
Antworten:
Beachten Sie, dass Sie selbst nach der
defun
Lösung des globalen Problems weitaus weniger Maschinen benötigen, als Sie für so etwas benötigen. Zum Beispiel:Dann
Offensichtlich
account-operation
ist nur eine Annehmlichkeit.quelle
Vielleicht möchten Sie Objektorientierung?
Verwendungszweck:
Wir können Konten mit einem anderen Saldo erstellen:
Für mehr empfehle ich das Kochbuch: https://lispcookbook.github.io/cl-cookbook/clos.html
quelle
Eine allgemeine Regel ist, dass
defun
nur verwendet werden sollte, wenn eine Funktion auf oberster Ebene definiert wird. So definieren Sie lokale Funktionen , die beiden speziellen Operatorenflet
undlabels
kann verwendet werden ( manuell ).Zum Beispiel:
labels
ist wieflet
, aber es wird verwendet, wenn es rekursive Definitionen gibt.Dann müssen Sie keine Funktionen innerhalb der von zurückgegebenen Funktion zurückgeben
make-acc
, aber darin können Sie einfach die erforderliche Operation ausführen:Der Aufruf ist einfacher und gibt den erwarteten Wert zurück:
Wenn Sie möchten, können Sie auch zwei verschiedene Funktionen zurückgeben, um Ein- und Auszahlungen auf dem Konto durchzuführen:
Verwenden Sie dies zum Beispiel als:
quelle
Das einzige ernsthafte Problem hier ist
defun
dass im Allgemeinen lisp nicht zum Definieren lokaler Funktionen verwendet wird.Sie könnten zum Beispiel
lambda
s für diese Operationen verwenden, insbesondere wenn Sie Lambdas zurückgeben möchten ...Beachten Sie, dass ich
let*
anstelle von verwendet habe,let
weil Sie in der Lage sein müssen,balance
in den beiden folgenden Bindungen zu sehen.quelle