LISPキーワードが保護されていないのはなぜですか?
例えば、
(define a 3)
(define define +) #makes define useless
(define a 1) #outputs 4, instead of assigning 1 to a.
この柔軟性はそれほど重要ですか?さらに悪いことに:
(define + -)
(+ 1 1) #Output 0.
これはどこで役立ちますか?また、この動作をブロックできますか? AFAIK、すべてのプログラミング言語には予約キーワードがあります。
Common LISPでは、パッケージ内のすべてのシンボルCOMMON LISP
は標準によって保護されています。パッケージまたはパッケージ内のシンボルを再定義すると、未定義の結果が生じると書かれています。つまり、すべてが発生する可能性があります。何も起こらない、変更が加えられる、プログラムがクラッシュする、プログラムでエラーが発生する、...、または翌朝、太陽が西に昇るなどです。
Real Common LISP実装は、ユーザーに警告することがよくあります。
Lispworks:
CL-USER 1 > (defun defun () 3)
Error: Redefining function DEFUN visible from package COMMON-LISP.
1 (continue) Redefine it anyway.
2 (abort) Return to level 0.
3 Restart top-level loop.
SBCL:
* (defun defun () 3)
debugger invoked on a SYMBOL-PACKAGE-LOCKED-ERROR:
Lock on package COMMON-LISP violated when proclaiming DEFUN as a function
while in package COMMON-LISP-USER.
See also:
The SBCL Manual, Node "Package Locks"
The ANSI Standard, Section 11.1.2.1.2
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE ] Ignore the package lock.
1: [IGNORE-ALL ] Ignore all package locks in the context of this operation.
2: [UNLOCK-PACKAGE] Unlock the package.
3: [ABORT ] Exit debugger, returning to top level.
多くのCommonLISP実装は、主にそれ自体でプログラムされているため、変更を許可し、後でそれらを防止するメカニズムが必要です。
言語の一部は、関数またはマクロを再定義しても変更できません。ユーザーが特殊な形式(LETなど)や引数リストやラムダ式などの特殊な構文を変更、追加、または削除する方法はありません。引数リストの構文は、言語に組み込まれています。 ラムダ式の構文はハードワイヤードです。変更することはできません。インタープリターやコンパイラーを変更する必要があります。
シンボルは保護する必要がないため、保護されません。一部の言語では、技術的には回避できたとしても、構文が「class」という名前のクラスを持つことを許容できないため、名前が予約されています。場合によっては、プログラマの心の曖昧さを回避するために意図的に行われ、-
を再定義して+
が理論上本当に悲惨なことになることを意味します。ただし、これは動的な環境の一部であり、このような柔軟性が役立つ場合があります。
mypackage:+
がyourpackage:+
と異なるように、さまざまな名前空間を使用すると、これらの問題はなくなります(+
の不適切な使用を開発中に検査して、実際に使用されているシンボルを確認できます)。
ちなみに、あなたの例はSchemeにあります(元々LISPとしてタグ付けしました)が、CommonLISPはその点で少し異なります。
標準化された「COMMON-LISP」パッケージの978シンボルは、ポータブルプログラムで再定義しないでください(これを行うと、未定義の動作になります)。 SBCLのような実装は、偶発的な変更を防ぐために、パッケージを「ロック」する方法を提供します。もちろん、それはあなたにそれらのロックを解除する方法を提供します。
通常、標準演算子を再定義するのではなく、独自のパッケージで定義された独自の演算子を提供するため、これは実際には問題ではありません。
パッケージはファーストクラスであるため、特定のパッケージにインポートされるシンボルを変更することもできます。これにより、修飾されていない+
関数の意味を変更するだけで、ファイルに触れずに既存のプログラムのセマンティクスを変更できる場合があります(および再コンパイル)。
これは、たとえば 自動微分 のような、ある種の instrumentation を実行するのに役立ちます。たとえば、プログラムに関する情報を計算するために、一連の演算子を独自のものに置き換えます。
LISPキーワードが保護されていないのはなぜですか?
これらはキーワードではないため、他のライブラリ関数と同じです。
これはどこで役に立ちますか、
これは、ユーザーとして、言語デザイナーと同じ力を持っていることを意味します。言語に変更を加えるには、数十年かかる可能性があり、大変な作業です。新しいライブラリ関数の作成は数秒で完了し、誰でも実行できます。
AFAIK、すべてのプログラミング言語には予約済みキーワードがあります。
いいえ、すべてではありません。たとえば、LISPはそうではありません。実際、LISPには実際には構文がまったくありません。
Ioにはキーワードがなく、IokeやSephもありません。ポイズンとポーションにもキーワードはありません。
Smalltalkにも非常に少数のキーワードがあります:true
、false
、nil
、self
、super
、およびthisContext
。 Newspeakにはほぼ同じリストがあります(true
、false
、nil
、self
、super
、outer
) 。どちらの場合も、nil
、true
、およびfalse
は、代わりに3つのキーワードだけを残して、同じように簡単にメソッド呼び出しにすることができます。 (実際、Newspeakの設計者であるGilad Brachaは、それらすべてをメソッド呼び出しにできると言っていましたが、それだけの価値はありません。)