10

Elisp で関数を返す関数を作成しました。

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  f)

これを IELM で実行しようとすると、失敗します。

ELISP> (singleton-set 5)
*** Eval error ***  Symbol's value as variable is void: f
ELISP> ((singleton-set 5) 5)
*** Eval error ***  Invalid function: (singleton-set 5)

Lisp-1 と Lisp-2 の違いは何ですか? 私はコードをに変更しました

(defun singleton-set (elem)
  (defun f (n) (= n elem))
  #'f)

への呼び出し(funcall (singleton-set 5) 5)ですが、現在エラーは

*** Eval error *** Symbol's value as variable is void: elem

elisp:capture variable from inner function から、これは Emacs Lisp の動的バインディングによるものだと理解しています。

Emacs Lispで関数を返す関数を可能にする方法は? このメカニズムが Python、Scala、Clojure などの他の言語と異なる理由は何ですか?

関連する質問:

4

3 に答える 3

11

NEWSfor Emacs 24から:

Emacs 24.1 での Lisp の変更点

  • コードは、動的スコープの代わりにデフォルトで字句スコープを使用できるようになりました。このlexical-binding変数は、ローカル変数のレキシカル スコープを有効にします。通常、ファイルの最初の行にあるファイル ローカル変数を介して設定されます。この場合、そのファイル内のすべてのコードに適用されます。

したがって、Emacs 24 では次のようになります。

(setq lexical-binding t)
(defun singleton-set (elem) (lambda (n) (= n elem)))
(mapcar (singleton-set 1) '(0 1 2 3))
    ===> (nil t nil nil)
于 2012-10-07T20:55:46.557 に答える
6

Emacs Lispで関数を返す関数を可能にする方法は?

偽のクロージャの使用、およびlexical-let.

このメカニズムが Python、Scala、Clojure などの他の言語と異なる理由は何ですか?

リチャード・ストールマンは、少し前に書いた論文でこの質問に答えました。

于 2012-10-07T20:32:44.600 に答える
3
(defun singleton-set (elem)
  `(lambda (n) (= n ,elem))

参照:パラメータおよび戻り値としての elisp 関数

于 2012-10-07T20:30:16.340 に答える