生成プログラミング用の非 C++ 言語?
-
02-07-2019 - |
質問
C++ はおそらく最も人気のある言語です。 静的メタプログラミング そして Javaはそれをサポートしていません.
C++以外にも生成プログラミング(プログラムを作成するプログラム)をサポートする言語はありますか?
解決
テンプレート スタイルのメタ プログラミングに代わる方法は、さまざまな Lisp 実装で見られるマクロ スタイルです。ダウンロードすることをお勧めします ポール・グレアムの Lisp について そしてまた見てみると クロージュア JVM 上で実行されるマクロを備えた Lisp に興味がある場合。
Lisp のマクロは C/C++ スタイルよりもはるかに強力で、それ自体で言語を構成します。マクロはメタプログラミングを目的としています。
他のヒント
リストしてみましょう いくつかの重要な詳細 方法について メタプログラミング 作品 Lispで (または スキーム, 、 または スレート, 、またはお気に入りの「動的」言語を選択します):
- Lispでメタプログラミングを行うときは、 2つの言語を扱う必要がない. 。メタ レベルのコードは、生成されるオブジェクト レベルのコードと同じ言語で記述されます。メタプログラミングは 2 つのレベルに限定されず、脳にも負担がかかりません。
- Lispには次のものがあります 実行時に利用可能なコンパイラ. 。実際、コンパイル時と実行時の区別は非常に人工的に感じられ、視点をどこに置くかによって大きく左右されます。lisp では、単なる関数呼び出しで関数を機械語命令にコンパイルでき、それ以降はファーストクラスのオブジェクトとして使用できます。つまりローカル変数やグローバル ハッシュテーブルなどに保持できる名前のない関数にすることもできます。
- マクロ Lisp では非常に単純です:ハッシュテーブルに詰め込まれてコンパイラに与えられる一連の関数。コンパイラーはコンパイルしようとしているフォームごとに、そのハッシュテーブルを参照します。関数が見つかった場合は、コンパイル時に元の形式でその関数を呼び出し、元の形式の代わりに、この関数が返す形式をコンパイルします。(いくつかの重要ではない詳細を法として) したがって、Lisp マクロ 基本的にはコンパイラ用のプラグインです.
- Lisp コードを評価する Lisp 関数を Lisp で書くと、約 2 ページのコードになります (これは通常、 評価)。このような関数では、メタ レベルで必要な新しいルールを導入するすべての権限が与えられます。(高速に動作させるには多少の努力が必要ですが...新しい言語をブートストラップするのとほぼ同じです...:)
ランダムな例 ユーザーライブラリとして実装できる lisp メタプログラミングを使用します (これらは一般的な lisp ライブラリの実際の例です):
- で言語を拡張する 区切られた継続 (hu.dwim.delico)
- を実装する jsからlisp-rpcへ JavaScript (LISP から生成される) で使用できるマクロ。これは、参照されたすべてのローカル変数を (http リクエストで) 自動的にポストし、サーバー側でデコードし、サーバー上で Lisp コード本体を実行し、戻り値を JavaScript に返す js/lisp コードの混合に展開されます。側。
- 「通常の」Lisp コードと非常にシームレスに統合する言語にバックトラックのようなプロローグを追加します (スクリーマーを参照)
- の XML テンプレート拡張機能 Common Lisp (の例を含む) リーダーマクロ これは Lisp パーサーのプラグインです)
- 大量の小さな DSL のような ループ または 反復する 簡単にループさせるために
テンプレートのメタプログラミングは、本質的にはテンプレート メカニズムの悪用です。私が言いたいのは、計画外の副作用である機能から期待されるものは基本的に得られるということです -- それはめちゃくちゃで、(ツールは改良されていますが) 言語がそうではないので本当に面倒ですそれを実行するのをサポートします(私はこのアプローチを本質的に放棄したため、これに関する最先端技術に関する私の経験は古いことに注意してください。大きな進歩があったという話は聞きませんが)
1998 年頃にこれをいじったことが、より良い解決策を探すきっかけになりました。これに依存した便利なシステムを書くことはできましたが、それは地獄のようなものでした。いろいろ調べてみたところ、最終的に Common Lisp にたどり着きました。確かに、テンプレートのメカニズムはチューリングで完全ですが、インターカルでも同様です。
Common Lisp はメタプログラミングを「正しく」実行します。実行中には、特別な構文を必要とせず、言語の全機能を利用できます。また、言語は非常に動的であるため、より多くのことを行うことができます。
もちろん他のオプションもあります。私がこれまでに使用した言語の中で、Lisp よりも優れたメタプログラミングを行う言語はありません。そのため、研究用コードに Lisp を使用しています。何か他のことを試してみたくなる理由はたくさんありますが、それはすべてトレードオフになります。Haskell/ML/OCamlなどを見ることができます。多くの関数型言語には、Lisp マクロの能力に近い機能があります。.NET を対象としたものはいくつか見つかりますが、それらはすべて (ユーザー ベースなどの観点から) 非常にわずかです。実際、工業的に使用されている言語の大手企業には、このようなものはありません。
ネメルレ そして ブー 私の個人的なお気に入りはそのようなものです。Nemerle は、ドキュメントが貧弱であるにもかかわらず、非常にエレガントなマクロ構文を備えています。Boo のドキュメントは優れていますが、マクロは少し洗練されていません。ただし、どちらも信じられないほどうまく機能します。
どちらも .NET をターゲットとしているため、C# や他の .NET 言語 (IKVM を使用している場合は Java バイナリも含む) と簡単に相互運用できます。
編集:明確にするために、ここで言っているのは Lisp の意味でのマクロのことであり、C のプリプロセッサ マクロのことではありません。これらにより、コンパイル時に新しい構文の定義と高度なメタプログラミングが可能になります。たとえば、Nemerle には、コンパイル時に SQL サーバーに対して SQL クエリを検証するマクロが付属しています。
Nim は、静的メタプログラミングを広範にサポートし、効率的な (C++ のような) コンパイル済みコードを生成する比較的新しいプログラミング言語です。
コンパイル時の関数評価、マクロによる Lisp のような AST コード変換、コンパイル時のリフレクション、任意の値でパラメータ化できるジェネリック型、およびユーザー定義の高レベルの型認識の作成に使用できる項の書き換えをサポートします。のぞき穴の最適化。コンパイル プロセス中に、コード生成に影響を与える可能性のある外部プログラムを実行することも可能です。例として、コード内の ORM 定義 (DSL を通じて提供される) がデータベースのスキーマと一致することを確認するために、ローカルで実行されているデータベース サーバーと通信することを考えてみましょう。
の 「D」プログラミング言語 C++ に似ていますが、メタプログラミングのサポートがはるかに優れています。以下は、コンパイル時のメタプログラミングのみを使用して作成されたレイトレーサーの例です。
さらに、C++ では (少なくともまだ) サポートしていないメタプログラミング構造をサポートする、「Concept GCC」と呼ばれる gcc ブランチがあります。
Common Lisp は、いくつかの異なる方法でプログラムを作成するプログラムをサポートしています。
1) プログラムデータとプログラム「抽象構文木」は統一されています (S 式!)
2) defmacro
3) リーダーマクロ。
4) MOP
このうち、本当に衝撃的なのは MOP です。「The Art of the Metaobjectプロトコル」を読んでください。それはあなたのために物事を変えるでしょう、私は約束します!
Haskell での多くの作業:ドメイン固有言語 (DSL)、実行可能仕様、プログラム変換、部分アプリケーション、段階的計算。始めるためのリンクがいくつかあります:
ML ファミリの言語は、この目的のために特別に設計されました。OCaml の最も有名な成功事例の 1 つは、 FFTW 高性能 FFT 用のライブラリ。ほぼ完全に OCaml プログラムによって生成された C コードです。
乾杯、ジョン・ハロップ。
ほとんどの人は、自己検査のための「究極の反省」と、新しいコードを具体化するための「評価」のようなものを持つ言語を見つけようとします。そのような言語は見つけるのが難しい(Lispは主要な反例です)、それらは確かに主流ではありません。
しかし、別のアプローチは、プログラムコードを検査、生成、および操作できる一連のツールを使用することです。ジャックポットは、Javaに焦点を当てたこのようなツールです。 http://jackpot.netbeans.org/
当社のDMSソフトウェアリエンジニアリングツールキットは、C、C ++、C#、Java、COBOL、PHP、JavaScript、ADA、Verilog、VHDL、およびその他のさまざまな言語で動作するこのようなツールです。(生産品質のフロントエンドを使用して、これらすべてのランガージュを読み取ることができます)。さらに良いのは、これを複数の言語で同時に実行できることです。見る http://www.semdesigns.com/Products/DMS/DMSToolkit.html
DMS が成功するのは、AST としてプログラム構造に完全にアクセスするための通常のメソッドとサポート インフラストラクチャ、およびほとんどの場合、高度なプログラム操作を行うために必要なシンボル テーブル、型情報、制御およびデータ フロー分析などの追加データを提供するためです。
「メタプログラミング」という名前は、少なくとも複数の言語について議論する場合には、この特定の機能の名前としてはあまり良くありません。この機能は、次のような狭い範囲の言語でのみ必要とされるからです。
- 静的
- 機械語にコンパイルされる
- コンパイル時のパフォーマンスを大幅に最適化
- ユーザー定義のデータ型で拡張可能 (C++ の場合は OOP)
- 大人気
これらのどれかを取り除いても、「静的メタプログラミング」はまったく意味がありません。したがって、C++ で理解されるような、遠隔の主流言語にそのようなものがあったとしたら、私は驚くでしょう。
もちろん、動的言語といくつかの関数型言語は、メタプログラミングとも呼ばれるまったく異なる概念をサポートしています。
Lisp は、C++ テンプレートのメタプログラミングと同じ意味ではありませんが、「メタプログラミング」の形式をサポートしています。また、この文脈では「静的」という用語は別の意味を持っている可能性がありますが、それがあなたの意味するところであれば、Lisp は静的型付けもサポートしています。
もちろんメタ言語 (ML) です: http://cs.anu.edu.au/student/comp8033/ml.html