Wie im folgenden Code definiert ich eine Funktion zum Erstellen einer Closure, die ein Argument akzeptiert, dessen Wert ein Symbol sein soll, das sich auf eine Variable bezieht, die im Kontext dieser Closure gebunden ist. Im Körper des Verschlusses verwende ich symbol-value
, um den Wert des Symbols zu erhalten, aber es erscheint ein Fehler, der Symbol's value as variable is void
sagt, ich erwarte, dass dieses Schnipsel 123
anzeigt.In Elisp, wie auf die Wertzelle eines Symbols zugreifen, das lokal von einem Abschluss gebunden ist?
hier So habe ich zwei Fragen:
- Warum
symbol-value
funktioniert nicht? - Wie korrigiere ich dieses Snippet, um das gewünschte Ergebnis zu erhalten?
(defun make-closure()
(lexical-let ((var1 123))
(lambda (name)
;; How can I get the value cell of the symbol
;; specified by the argument "name" ?
;; This doesn't work.
(message-box (format "%s" (symbol-value name))))))
(let ((closure (make-closure)))
(funcall closure 'var1))
Aktualisiert:
Eigentlich habe ich diese Frage, als ich einige Spielzeug-Code ahmen "Object Oriented" zu schreiben. Zuerst war es so etwas wie dies (die auf den zweiten Code von Stefan Antwort ähnlich ist):
(defun new-person (initial-name)
(lexical-let* ((name initial-name)
(say-hi (lambda()
(message-box (format "Hi, I'm %s" name))))
(change-name (lambda (new-name)
(setq name new-name))))
(lambda (selector &rest args)
(cond
((equal 'say-hi selector) (apply say-hi args))
((equal 'change-name selector) (apply change-name args))
(t (message-box "Message not understood"))))))
(let ((tony (new-person "Tony")))
(funcall tony 'say-hi)
(funcall tony 'change-name "John")
(funcall tony 'say-hi))
Aber fühlte ich die Klauseln „cond“ irgendwie „vorformulierten“ und ich dachte, es könnte möglich sein, verwenden sie das Symbol aus dem Argument übergeben, so dass ich modifiziert es auf die folgenden, die nicht mehr funktioniert, aber ich konnte nicht Figur heraus, warum:
(defun new-person (initial-name)
(lexical-let* ((name initial-name)
(say-hi (lambda()
(message-box (format "Hi, I'm %s" name))))
(change-name (lambda (new-name)
(setq name new-name))))
(lambda (selector &rest args)
(apply (symbol-value selector) args))))
damit, dass wir nicht sagen, verwenden sollten Ein Symbol, das auf eine lexikalisch gebundene Variable in a verweist Schließung wie oben, da die Namen von ihnen bei der Bewertung sind nicht garantiert, dass sie die gleichen sind wie sie in der Quelle geschrieben sind?
Lexikalische Variablen sollen einfach nicht von außerhalb des Verschlusses zugänglich sein. Das ist mehr oder weniger der Sinn von ihnen. Wenn Sie auf diese Variablen zugreifen müssen, dann war die lexikalische Bindung in erster Linie die falsche Wahl, und ich glaube nicht, dass es eine gute Idee ist, nach Wegen zu suchen. – phils