LISPのマクロは、DSLを作成するRubyの「能力」よりも優れているのはどの領域ですか


21

Rubyを輝かせるものの1つは、ドメイン固有の言語をより良く作成する機能です。

マクロを介してLISPでこれらのライブラリを複製できますが、Rubyの実装はよりエレガントだと思います。それでも、LISPのマクロはRubyのマクロよりも優れている場合があると思いますが、マクロは考えられませんでした。

それでは、LISPのマクロは、DSLを作成するRubyの「能力」よりも優れているのはどの領域ですか。

更新

現代のプログラミング言語がLISPの特異点近づいているので、私はこれを尋ねました。

  • Cはマクロ展開プリプロセッサを取得しましたが、非常に原始的でエラーが発生しやすい
  • C#には属性がありますが、これは読み取り専用であり、リフレクションによって公開されます
  • Pythonは、関数(およびv 3.0のクラス)の動作を変更できるデコレーターを追加しましたが、かなり制限されています。
  • 気をつければエレガントなDSLを作成するRuby TMTOWTDIですが、Rubyの方法です。

LISPのマクロは特別な場合にのみ適用でき、他のプログラミング言語機能はソフトウェア開発の今日の課題に対応するために抽象化を高めるのに十分強力であると思いました。


4
これになぜ賛成票があるのか​​、私にはよくわかりません。私はこれが私たちが望む種類の質問ですか?おもしろい、考えさせる、そしてスコープは非常によく定義されています。
ティムポスト

Rubyで次のようなものを実装してみてください:meta-alternative.net/pfront.pdf
SK-logic

@Tim Post:1つの問題は、Common LispとRubyの両方をよく知っていない限り、これは本当に答えが簡単な質問ではないということです。もう1つは他の言語へのかなり無知な参照であり、純粋主義者を悩ませる可能性があります.C / C ++と呼ばれる言語はなく、C ++の重要な部分はテンプレートシステムであり、Common Lispのマクロシステムは特別な場合にのみ適用可能であるという提案です。基本的に、それは良い質問ですが、書き方が悪く、答えるのが難しいです。
デビッドソーンリー

@David Thornley、私は投稿、特にC \ C ++を更新し、Cに重点を置きました。CommonLispに関しては、他のプログラミング言語はより高い抽象性を持っているので、マクロ機能は特別な場合のためです。私は質問を投稿しました。CLのマクロが特別な場合のためではないことを他の人が私に示すこと期待して、まだ強力な機能です。
-OnesimusUnbound

@OnesimusUnbound:少なくとも理論的にはLispマクロシステムが実行できる計算が可能なため、C ++のテンプレートを言語の例のリストに含めます。Lispのマクロに関しては、いくつかの優れたCommon Lispコードを入手し(そこにはF / OS Lispコードがたくさんあります)、「defmacro」を検索します(大文字と小文字を区別しない検索を実行することもできます)。あなたはおそらくそれらの多くを見つけるでしょう。マクロは関数を書くよりも難しく、正しく動作することを考慮してください。マクロは一般的に有用でなければならないことに気付くでしょう。
デビッドソーンリー

回答:


23

On Lispを読んで、自分で決めてください。

私の要約は、Rubyは便利な構文を提供するのに優れているということです。しかし、Lispは、新しい抽象化を作成し、抽象化に抽象化を重ねる能力で勝ち、伝承します。しかし、その点を理解するには、実際にLispを見る必要があります。したがって、本はお勧めします。


1
「Let Over Lambda」は、ほぼ同様の分野をカバーしています。また、読書をお勧めします。
ジョンR.ストローム

But Lisp wins, hands down, at the ability to create new abstractions, and then to layer abstraction on abstraction.今、私は理由を知っています。。。
-OnesimusUnbound

Lispの上にあらゆる種類の構文を提供することは大したことではありません。実際、リーダーマクロのおかげで、Rubyよりもはるかに簡単です。
SKロジック

1
@ SK-logic:True。ただし、Lispersはリーダーマクロを避けます。そのルートをたどると、Lispのように感じられなくなるからです。実際、ClojureなどのLispの一部のバリアントは、言語デザイナー用にリーダーマクロを予約しています。
btilly

14

DSLオーサリングのためのRubyの機能は、言語の性質を変えません。Rubyのメタプログラミング機能は本質的にRubyの構文とセマンティクスに結び付けられており、作成するものはすべてRubyのオブジェクトモデルに迂回する必要があります。

それとは対照的に、Lisp(およびマクロ機能が異なる Scheme )では、マクロは抽象プログラム自体で動作します。Lispプログラム Lisp値であるため、マクロは本質的に任意の構文を別の構文にマッピングする関数です。

実際には、RubyのDSLはまだ感じている Rubyのような、しかし、LispのDSLは、Lispのように感じる必要はありません。


6
+1:DSLの例として、LOOPはあまりLispyを感じません。
フランク・シーラー

2

RubyのDSLはまったくDSLではありません。Rubyのドキュメントは、それらが実際にどのように機能するかを完全に説明しているため、使用することは絶対に嫌いです。ActiveRecordを例にとってみましょう。モデル間の関連付けを「宣言」できます。

class Foo < ActiveRecord::Base
    has_one :bar
    has_one :baz
end

しかし、この「DSL」の宣言性(Rubyのclass構文自体の宣言性のような)は恐ろしい嘘であり、Rubyの「DSL」が実際にどのように機能するかを理解している人なら誰でも暴露することができます。

class Foo < ActiveRecord::Base
    [:bar,:baz,:qux,:quux].each do |table|
        has_one table if i_feel_like_it?(table)
    end
    puts "Just for shits and giggles, and to show"
    puts "just how fucked up Ruby really is, we're gonna ask you"
    puts "which SQL table you want the Foo model to have an"
    puts "association with.\n"
    puts "Type the name of a table here: "
    has_one gets.chomp.to_sym
end

(Lisp フォームの本体内でそれに近いものを試してみてくださいdefclass!)

上記のようなコードがコードベースにあるとすぐに、プロジェクトのすべての開発者は、Ruby DSLが実際にどのよう動作するか(作成した幻想だけでなく)を完全に理解してからコードを維持する必要があります。利用可能なドキュメントは、宣言的な錯覚を保持する慣用的な使用法のみをドキュメント化するため、まったく役に立ちません。

RSpecは、デバッグするために広範なリバースエンジニアリングを必要とする奇妙なエッジケースを持っているため、上記よりもさらに悪いです。(テストケースの1つがスキップされた理由を解明するために丸1日を費やしました。RSpecは、ソースに表示される順序に関係なく、コンテキストのないテストケースの後にコンテキストを持つすべてのテストケースを実行することが判明しました、contextメソッドがブロックを通常のデータ構造とは異なるデータ構造に配置するため。

Lisp DSLはマクロによって実装されますが、マクロは小さなコンパイラです。この方法で作成できるDSLは、Lispの既存の構文の単なる乱用ではありません。それらは、独自の文法を持つことができるため、完全にシームレスになるように記述できる実際のミニ言語です。たとえば、LispのLOOPマクロはRubyのeachメソッドよりもはるかに強力です。

(あなたがすでに答えを受け入れていることは知っていますが、これを読むすべての人がOn Lisp全体を読みたいとは限りません。)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.