50

おそらくマクロを使用して、LISPがオンザフライで構文を再定義できることをたくさん読んだことがあります。私はこれが実際にどこまで行くのか興味がありますか?言語構造を再定義して、境界線が別の言語のコンパイラになることはありますか? たとえば、LISP の機能的な性質を、よりオブジェクト指向の構文とセマンティクスに変更できますか。たとえば、Ruby のようなものに近い構文を使用できますか?

特に、マクロを使って括弧地獄をなくすことはできますか?私は (Emacs-) LISP を十分に学んだので、Emacs を独自のマイクロ機能でカスタマイズすることができましたが、マクロを使って言語をどこまでカスタマイズできるのか非常に興味があります。

4

14 に答える 14

36

それは本当に良い質問です。

私はそれが微妙なニュアンスがあると思いますが、間違いなく答えられます:

マクロはS式に固定されていません。キーワード(記号)を使用して記述された非常に複雑な言語については、LOOPマクロを参照してください。したがって、ループを括弧で開始および終了することもできますが、ループ内には独自の構文があります。

例:

(loop for x from 0 below 100
      when (even x)
      collect x)

そうは言っても、ほとんどの単純なマクロはS式を使用するだけです。そして、あなたはそれらを使って「行き詰まる」でしょう。

しかし、セルジオが答えたように、S式は正しいと感じ始めます。構文が邪魔にならず、構文ツリーでコーディングを開始します。

リーダーマクロに関しては、はい、おそらく次のように書くことができます。

#R{
      ruby.code.goes.here
  }

ただし、独自のRuby構文パーサーを作成する必要があります。

また、既存のLispコンストラクトにコンパイルされるマクロを使用して、ブロックなどのRubyコンストラクトの一部を模倣することもできます。

#B(some lisp (code goes here))

に翻訳されます

(lambda () (some lisp (code goes here)))

その方法については、このページを参照してください。

于 2008-09-15T15:07:21.940 に答える
24

はい、Lisp がコンパイラになるように構文を再定義できます。これは、おそらく皆さんが考えている通常の「コンパイラ マクロ」とは異なる「リーダー マクロ」を使用して行います。

Common Lisp には、リーダー用の新しい構文を定義する組み込み機能と、その構文を処理するためのリーダー マクロがあります。この処理は、読み取り時 (コンパイルまたは評価時間の前) に行われます。Common Lisp でリーダー マクロを定義する方法の詳細については、Common Lisp Hyperspec を参照してください。Ch. 2、「構文」およびCh。23、「リーダー」。(Scheme にも同じ機能があると思いますが、私はそれに慣れていません。Arc プログラミング言語のScheme ソースを参照してください)。

簡単な例として、Lisp に括弧ではなく中括弧を使用させたいとしましょう。これには、次のようなリーダー定義が必要です。

;; { and } become list delimiters, along with ( and ).
(set-syntax-from-char #\{ #\( )
(defun lcurly-brace-reader (stream inchar) ; this was way too easy to do.
  (declare (ignore inchar))
  (read-delimited-list #\} stream t))
(set-macro-character #\{ #'lcurly-brace-reader)

(set-macro-character #\} (get-macro-character #\) ))
(set-syntax-from-char #\} #\) )

;; un-lisp -- make parens meaningless
(set-syntax-from-char #\) #\] ) ; ( and ) become normal braces
(set-syntax-from-char #\( #\[ )

{ は ( のようなものであり、} は ) のようなものであることを Lisp に伝えています。次にlcurly-brace-reader、リーダーが { を検出するたびに呼び出す関数 ( )を作成し、set-macro-characterその関数を { に割り当てるために使用します。次に、( と ) は [ と ] に似ている (つまり、意味のある構文ではない) ことを Lisp に伝えます。

他にできることには、たとえば、新しい文字列構文を作成したり、[ と ] を使用して中置記法を囲み、それを S 式に処理したりすることが含まれます。

これをはるかに超えて、リーダーでアクションをトリガーする独自のマクロ文字を使用して構文全体を再定義することもできます。空は本当に限界です。これは、 Paul Grahamの人々が、Lisp はコンパイラを書くのに適した言語であると言い続けている理由の 1 つにすぎません。

于 2008-09-16T19:28:28.607 に答える
16

私はLispの専門家ではなく、Lispプログラマーでもありませんが、言語を少し実験した後、しばらくすると括弧が「非表示」になり始め、コードが次のように表示されるようになるという結論に達しました。あなたはそれをしたいです。リストと括弧のテキストの字句形式ではなく、s-exprsとマクロを介して作成する構文構造にもっと注意を払い始めます。

これは、インデントと構文の色付けに役立つ優れたエディターを利用する場合に特に当てはまります(括弧を背景に非常に似た色に設定してみてください)。

言語を完全に置き換えて「Ruby」構文を取得することはできないかもしれませんが、それは必要ありません。言語の柔軟性のおかげで、必要に応じて、「ルビースタイルのプログラミング」に従っているように感じる方言を終わらせることができます。

これは単なる経験的な観察であると私は知っていますが、私がこれに気付いたとき、私はそれらのLisp啓蒙の瞬間の1つを持っていたと思います。

于 2008-08-26T09:49:02.323 に答える
15

何度も繰り返しますが、Lisp の初心者は「すべての括弧を取り除きたい」と思っています。それは数週間続きます。通常の S 式パーサーの上に本格的な汎用プログラミング構文を構築するプロジェクトは、どこにも行き着きません。なぜなら、プログラマーは常に、現在「括弧地獄」と認識されているものを好むことになるからです。慣れるまで少し時間がかかりますが、大したことはありません! 慣れると、デフォルトの構文の可塑性を本当に理解できるようになり、特定のプログラミング構造を表現する方法が 1 つしかない言語に戻るのは本当に面倒です。

そうは言っても、Lisp はドメイン固有言語を構築するための優れた基盤です。XML と同じか、それ以上ではありません。

幸運を!

于 2008-09-16T19:29:54.763 に答える
14

私がこれまでに見た Lisp マクロの最良の説明は、

https://www.youtube.com/watch?v=4NO83wZVT0A

約 55 分から始まります。これは、最高の Lisp 教科書である「Practical Common Lisp」の著者である Peter Seibel による講演のビデオです。

Lisp マクロの動機を説明するのは、通常、説明が困難です。単純なチュートリアルで説明するには長すぎる状況で、Lisp マクロが真価を発揮するからです。ピーターは素晴らしい例を思いつきます。完全に把握でき、Lisp マクロを適切に使用できます。

あなたは、「LISP の機能的な性質を、よりオブジェクト指向の構文とセマンティクスに変更できますか?」と尋ねました。答えはイエスです。実際、Lisp にはもともとオブジェクト指向プログラミングがまったくありませんでした。これは、Lisp がオブジェクト指向プログラミングよりずっと前から存在していたことを考えると驚くことではありません。しかし、1978 年に初めて OOP について学んだとき、特にマクロを使用して、Lisp に簡単に追加することができました。最終的に Common Lisp Object System (CLOS) が開発されました。これは、Lisp にエレガントに適合する非常に強力なオブジェクト指向プログラミング システムです。すべてを拡張機能としてロードできます。何も組み込まれていません! すべてマクロでできています。

Lisp には、「リーダー マクロ」と呼ばれるまったく異なる機能があり、言語の表面構文を拡張するために使用できます。リーダー マクロを使用すると、C ライクまたは Ruby ライクな構文を持つサブ言語を作成できます。内部でテキストを Lisp に変換します。これらは、ほとんどの実際の Lisp プログラマーによって広く使用されていません。主な理由は、インタラクティブな開発環境を拡張して新しい構文を理解することが難しいためです。たとえば、Emacs のインデント コマンドは、新しい構文によって混乱する可能性があります。しかし、あなたが精力的であれば、Emacs も拡張可能であり、新しい字句構文について Emacs に教えることができます。

于 2008-10-05T15:03:31.263 に答える
11

かっこ地獄?次の括弧はもう表示されません。

(function toto)

よりも:

function(toto);

そしてで

(if tata (toto)
  (titi)
  (tutu))

に過ぎない:

if (tata)
  toto();
else
{
  titi();
  tutu();
}

角かっこと';'が少なくなります けれど。

于 2008-09-16T16:23:18.287 に答える
11

通常のマクロは、オブジェクトのリストを操作します。最も一般的には、これらのオブジェクトは他のリスト(したがってツリーを形成する)およびシンボルですが、文字列、ハッシュテーブル、ユーザー定義オブジェクトなどの他のオブジェクトにすることもできます。これらの構造はs-expsと呼ばれます。

したがって、ソースファイルをロードすると、Lispコンパイラがテキストを解析してs-expsを生成します。マクロはこれらを操作します。これはうまく機能し、s-expsの精神の範囲内で言語を拡張する素晴らしい方法です。

さらに、前述の解析プロセスは、コンパイラがテキストをs-expsに変換する方法をカスタマイズできる「リーダーマクロ」を介して拡張できます。ただし、Lispの構文を別のものに曲げるのではなく、受け入れることをお勧めします。

Lispの「機能的性質」とRubyの「オブジェクト指向構文」について言及すると、少し混乱しているように聞こえます。「オブジェクト指向構文」がどうあるべきかはわかりませんが、Lispはマルチパラダイム言語であり、オブジェクト指向プログラミングを非常にうまくサポートしています。

ところで、私がLispと言うとき、私はCommonLispを意味します

私はあなたがあなたの偏見を片付けて、Lispに正直に行くことを提案します。

于 2008-08-26T09:36:27.020 に答える
9

あなたが尋ねていることは、お気に入りのチョコレートケーキから地獄のような茶色のものをすべて取り除くことができるように、専門のショコラティエになる方法を尋ねるようなものです.

于 2008-09-17T12:14:53.087 に答える
6

はい、構文を根本的に変更し、「括弧地獄」から逃れることさえできます。そのためには、新しいリーダー構文を定義する必要があります。リーダー マクロを調べます。

しかし、そのようなマクロをプログラムするための Lisp の専門知識のレベルに到達するには、括弧を「地獄」と見なさない程度に言語に没頭する必要があるのではないかと思います。つまり、それらを回避する方法を知る頃には、それらを良いこととして受け入れるようになるでしょう.

于 2008-09-15T12:07:06.287 に答える
2

Lisp を Ruby のように見せたい場合は、Ruby を使用します。

Ruby (および Python) を Lisp のような方法で使用することが可能であり、これがすぐに受け入れられた主な理由の 1 つです。

于 2008-08-05T07:40:26.980 に答える
2

リーダー マクロが XML テンプレート作成のような複雑なタスクで Lisp リーダーを拡張する方法のこの例を参照してください。

http://common-lisp.net/project/cl-quasi-quote/present-class.html

このユーザー ライブラリは、コンパイル時に XML の静的部分を UTF-8 でエンコードされたリテラル バイト配列にコンパイルし、ネットワーク ストリームに書き込みシーケンスを実行できるようにします。それらは通常の Lisp マクロで使用でき、直交しています... コンマ文字の配置は、どの部分が定数で、どの部分が実行時に評価されるべきかに影響します。

詳細については、http: //common-lisp.net/project/cl-quasi-quote/を参照してください。

Common Lisp 構文拡張用の別のプロジェクト: http://common-lisp.net/project/cl-syntax-sugar/

于 2008-09-17T00:30:43.247 に答える
1

私の頭を悩ませたマクロの使用法の1つは、DBに対するSQL要求のコンパイル時の検証でした。

コンパイル時に完全な言語が手元にあることに気付くと、興味深い新しい視点が開かれます。これはまた、興味深い新しい方法で自分の足を撃つことができることを意味します(コンパイルを再現できないようにするなど、デバッグの悪夢に非常に簡単に変わる可能性があります)。

于 2008-09-19T10:43:32.133 に答える
1

難しい質問です。Lisp はすでに構造的に解析ツリーに非常に近いため、多数のマクロと、パーサー ジェネレーターに独自のミニ言語を実装することの違いはあまり明確ではありません。しかし、開き括弧と閉じ括弧を除けば、Lisp とはまったく違うものになってしまう可能性があります。

于 2008-08-06T12:14:12.213 に答える
1

@スパークス

LISP が明確な言語の選択、つまり Emacs 拡張機能である場合があります。Rubyを使ってEmacsを拡張することもできると思いますが、EmacsはLISPで拡張するように設計されているので、そのような状況で使用するのは理にかなっているようです。

于 2008-08-05T07:45:14.020 に答える