以下のコードのように、1つの引数を受け入れるクロージャを作成する関数を定義します。この値は、このクロージャのコンテキストでバインドされた変数を参照するシンボルになります。クロージャーの本体では、symbol-value
を使用してシンボルの値を取得しますが、エラーはSymbol's value as variable is void
と表示されます。このスニペットを評価すると123
と表示されます。 symbol-value
が動作しないのはなぜElispでは、クロージャからローカルにバインドされたシンボルの値セルにアクセスする方法は?
- :
は、だからここに私は2つの質問がありますか?
- 希望の結果を得るためにこのスニペットを修正するにはどうすればよいですか?更新
(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))
実は、私はこの質問を得ました。最初は( はステファンの答えの第二のコードに似ている)、このようなものだった:
(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))
しかし、私は「指揮」ちょっと「決まり文句」の句を感じ、私はそれが をすることは可能かもしれないと思いました
(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))))
だから、我々が使用してはならないということである: は、もはや機能しており、次のようにそれを変更していないが、私はできません フィギュアアウトなぜ引数から渡されたシンボルを使用するので、I字句的に結合された変数を参照するシンボル。上記のように閉鎖してください。 の評価には、 が書かれているのと同じように保証されているわけではありません。
字句変数は、単にクロージャの外側からアクセスできるようにはなっていません。それは多かれ少なかれそのポイントです。これらの変数にアクセスする必要がある場合は、最初はレキシカルバインディングが間違った選択だったので、それを回避しようとするのは良い考えではないと思います。 – phils