3

Emacs 24の新しい字句スコープ機能がなぜそれほど素晴らしいのか理解できない理由は、それらなしでは実装できなかった新しい機能を考えることができないからです。たとえば、次のクロージャー:

(setq lexical-binding t)
(defun f1 (num1)
  (lambda (num2)
    (setq num1 (* num1 num2))))

(fset 'f2 (f1 5))
  ==> (closure ((num1 . 5) t) (num2) (setq num1 (* num1 num2)))
(f2 5)
  ==> 25
(f2 2)
  ==> 50

次のような通常の動的スコープで実装できます。

(defun f1 (num)
  (let ((tmpvar (make-symbol "num")))
    (set tmpvar num)
    `(lambda (num2)
       (set ',tmpvar (* (eval ,tmpvar) num2)))))

(fset 'f2 (f1 5))
  ==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f2 5)
  ==> 25
(f2 2)
  ==> 50
(fset 'f3 (f1 9))
  ==> (lambda (num2) (set (quote num) (+ (eval num) num2)))
(f3 3)
  ==> 27
(f3 2)
  ==> 54
(f2 10)
  ==> 500

さて、すべての言語がelispのインターンされていない記号に類似したものを持っているわけではないので、なぜそれらの場合に字句スコープが非常に優れているのか理解しています。しかし、elispはどうですか?字句スコープのおかげで、以前はできなかった(Emacs 24の時点で)今できることは何でも考えられますか?

4

3 に答える 3

5

インターンされていないシンボルは必要ありません。代わりに 、 の代わりに 、および の代わりに使用するconsmake-symbolcarevalsetcar同様setに機能します (より効率的になります)。

また、機械語から高水準言語への進歩は、ほとんどの場合、ますます多くのことを不可能にする(または少なくともはるかに困難にする) ことに基づいていることに注意してください。もちろん、プログラマーから奪われたこれらの機能は、めったに使用されなかったり、危険すぎると見なされたりすることはありませんでした。初期化されていない変数 (C では可能ですが、Java やその他の多くの言語では不可能) を使用したり、命令の途中にジャンプしたりすることを考えてみてください。

サンプルコードのいくつかの欠点については、読みにくいだけでなく、コンパイラは基本的にコードを構築していることを認識できないため、その "`(lambda .. .)" をコンパイルし、マクロ呼び出しを展開し、疑わしい要素について警告を表示します...

于 2012-08-26T02:58:45.787 に答える
4

Emacs ではレキシカル バインディングをシミュレートするための回避策が常に存在するため、新しいことができるようになることはそれほど重要ではありません。

マニュアルには次のように書かれています。

レキシカル バインディングは最適化の可能性をさらに広げるので、レキシカル バインディングを利用する Emacs Lisp コードは、将来の Emacs バージョンでより高速に実行される可能性があります。このようなコードは、並行性に対してもはるかに友好的であり、近い将来 Emacs に追加したいと考えています。

それが一番のメリットだと思います。

これとは裏腹に、Emacs が作成されたときに動的バインディングが意図的に選択されたということは、今日でも当てはまる正当な理由があるため、レキシカル バインディングを物事の新しい方法と見なすべきではありません。

グローバル変数は、一般的にプログラミングでは悪い考えと考えられていますが、Emacs はこれが実際には当てはまらない珍しいケースです。なぜなら、Emacs を優れたものにしている重要な要素の 1 つであるその非常に大きな柔軟性の多くは、動的バインディングから直接派生しているからです。動的バインディングがなければ、Emacs が許す限り、個々のユーザーの要件に合わせてアプリケーションを曲げることはできません。

私の意見では、字句バインディングは慎重に使用し、別のユーザーがオーバーライドする理由をおそらく見つけられない変数に対してのみ使用する必要があります。デフォルトでdefvarは、動作をカスタマイズする機能 (作成者が予期していなかった方法であっても) が維持されるように、変数を 'd にする必要があります。

于 2012-08-26T04:04:14.080 に答える
0

オブジェクト指向プログラミングの実装は、レキシカル スコープにうまく適合する傾向があると思います。状態を持つオブジェクトは、レキシカル クロージャに直接マップされます。

Common Lisp での CLOS の実装は、レキシカル スコープを大いに活用していると確信しています。その仕様を動的スコープだけで実装する方法を想像するのは難しいですが、それは可能だと確信しています。

于 2012-08-26T20:57:07.683 に答える