web-dev-qa-db-ja.com

メタプログラミングとは正確には何ですか?

TheServerSideの記事を読んでいた ployglot programming on the Java platform 。記事内のいくつかのコメントは、メタプログラミングをコードを生成する機能としています)。

その場でコードを生成する機能をメタプログラミングするか、実行時に既存のオブジェクトにメソッドと属性を注入する機能です(Python、Ruby、Groovyなどの一部の動的言語が許可するように)。

107
Parag

メタプログラミングとは、プログラムがそれ自体の知識を持っている、またはプログラムを操作できるさまざまな方法を指します。

C#のような言語では、プログラムは自身に関する情報を調べることができるため、リフレクションはメタプログラミングの一種です。たとえば、オブジェクトのすべてのプロパティのリストを返します。

ActionScriptのような言語では、実行時に関数を評価して、eval( "x" + i)などの新しいプログラムを作成できます。DoSomething()は、iが1の場合はx1、iが2の場合はx2.

最後に、メタプログラミングのもう1つの一般的な形式は、プログラムが自明ではない方法で変更できる場合です。 LISPはこのことで有名で、約10年前にPaul Grahamが擁護したものです。彼の具体的なエッセイのいくつかを調べなければなりません。しかし、アイデアは、プログラムがその状態に基づいてプログラムの別の部分を変更するということです。これにより、今日のほとんどの一般的な言語では非常に難しい実行時の決定を行うための柔軟性が得られます。

また、従来のストレートアセンブリでのプログラミングの昔の時代には、実行時に自分自身を変更するプログラムが必要であり、非常にありふれたものであったことも注目に値します。

Paul Grahamのエッセイから 「LISPを差別化したもの」

多くの言語にはマクロと呼ばれるものがあります。ただし、LISPマクロは一意です。信じられないかもしれませんが、彼らがしていることは括弧に関係しています。 LISPの設計者は、これらのすべてのかっこを単に異なる言語に入れたわけではありません。 Blubプログラマーにとって、LISPコードは奇妙に見えます。しかし、それらの括弧は理由があります。これらは、LISPと他の言語との根本的な違いの外見上の証拠です。

LISPコードは、LISPデータオブジェクトから作成されます。また、ソースファイルに文字が含まれているという些細な意味ではなく、文字列は言語でサポートされているデータ型の1つです。 LISPコードは、パーサーによって読み取られた後、横断可能なデータ構造で構成されます。

コンパイラがどのように機能するかを理解していれば、実際に何が起こっているかは、LISPには構文がないため、LISPには奇妙な構文があるということではありません。他の言語が解析されるときにコンパイラ内で生成される解析ツリーでプログラムを作成します。ただし、これらの解析ツリーにはプログラムから完全にアクセスできます。それらを操作するプログラムを作成できます。 LISPでは、これらのプログラムはマクロと呼ばれます。彼らはプログラムを書くプログラムです。

プログラムを書くプログラム?いつそれをしたいですか? Cobolで考えると、それほど頻繁ではありません。 LISPで考える場合、常に。強力なマクロの例を挙げて、そこに言うことができれば便利です。どのようにそのことについて?しかし、私がそうすれば、それはLISPを知らない人には意味がわからないように見えるでしょう。ここには、その意味を理解するために知っておく必要のあるすべてのことを説明する余地はありません。 Ansi Common LISP 私はできるだけ速く物事を進めようとしましたが、それでも160ページまでマクロに到達しませんでした。

しかし、私は説得力があるかもしれない一種の議論を与えることができると思います。 Viawebエディターのソースコードは、おそらく20〜25%のマクロでした。マクロは、通常のLISP関数よりも作成が難しく、必要のないときにマクロを使用するのは悪いスタイルと見なされます。そのため、そのコード内のすべてのマクロは、ある必要があるためそこにあります。つまり、このプログラムのコードの少なくとも20〜25%が、他の言語では簡単に実行できないことを実行しているということです。しかし、BlubプログラマーがLISPの不思議な力に対する私の主張について懐疑的であるかもしれませんが、これは彼を好奇心をそそるはずです。私たちは自分の娯楽のためにこのコードを書いていませんでした。私たちは小さなスタートアップであり、私たちと競合他社との間に技術的な障壁を設けるために、できる限りハードにプログラミングしていました。

疑わしい人は、ここに何らかの相関関係があるかどうか疑問に思うかもしれません。私たちのコードの大きな部分は、他の言語では非常に難しいことをしていました。結果として得られたソフトウェアは、競合他社のソフトウェアではできなかったことを行いました。何らかの関係があったのかもしれません。そのスレッドに従うことをお勧めします。老人は、目の届くよりも松葉杖を使ってホブリングしています。

78
DavGarcia

いい質問ですね。現在、どの質問にもあなたの質問に正しく答えられていないことが非常に残念です。おそらく私は助けることができます...

メタプログラミングの定義は本当に簡単です。プログラムを操作するプログラムを意味します。

受け入れられた答えは、自分自身を操作するプログラムを言う。これらは確かにメタプログラムですが、すべてのメタプログラムのサブセットです。

すべて:

  • パーサー
  • ドメイン固有言語(DSL)
  • 組み込みドメイン固有言語(EDSL)
  • コンパイラー
  • 通訳者
  • 期間リライタ
  • 定理証明

メタプログラムです。 GCCコンパイラ はメタプログラム、- CPythonインタープリター はメタプログラム、- Mathematicaコンピュータ代数システム はメタプログラム、 Coq定理証明者 はメタプログラムなどです。

他の答えは、メタプログラムは他のプログラムを生成するプログラムであると断言しています。これらは確かにメタプログラムですが、これもすべてのメタプログラムのサブセットです。 西で最も速いフーリエ変換 (FFTW)ライブラリは、そのようなメタプログラムの例です。ソースコードは主に OCaml で記述され、高性能を作成するために結合されるCコード(コードレットと呼ばれる)のビットを生成します 高速フーリエ変換 特定のマシンに最適化されたルーチン。このライブラリは、実際にはMatlabでFFTルーチンを提供するために使用されます。 [〜#〜] fortran [〜#〜] の初期の頃から、人々は数十年にわたって数値的手法を生成するプログラムを書いてきました。

メタプログラミングのサポートを統合した最初のプログラミング言語は、1950年代後半のLIStプロセッサ(LISP)言語でした。 LISP 1.5 には、メタプログラミングを容易にする多くの機能が含まれていました。まず、LISPのコアデータ型はネストされたリスト、つまり(a (b c) d)のようなツリーです。つまり、LISPコードはデータ構造としてネイティブに表現できます。これはホモイコニシティとして知られています。第二に、LISPコードはQUOTEを使用して簡単にデータに変換できます。たとえば、(+ 1 2 3)は1 + 2 + 3を追加し、(QUOTE (+ 1 2 3))は評価時に1 + 2 + 3を追加する式を作成します。 3番目に、LISPは、実行時に生成されたLISPコードを含む、実行時にLISPコードを評価するためにホストインタープリターまたはコンパイラを使用できるメタ循環エバリュエーターを提供しました。 LISPの子孫には Scheme および Clojure が含まれます。これらのすべての言語で、メタプログラミングは、通常はマクロを使用して自分自身を変更するプログラムの形で最も一般的に見られます。

1970年代に、Robin Milnerは MetaLanguage (ML)を開発しました。これは、 標準ML および OCaml を含むプログラミング言語のMLファミリに進化しました。影響を受ける Haskell および F# 。これらの言語により、他の言語を簡単に表現できます。これらの言語では、メタプログラムはレクサー、パーサー、インタープリター、コンパイラーの形で最も一般的に見られます。

1994年、 Erwin Unruhは、C++テンプレートシステムがチューリング完全であり、コンパイル時に任意のプログラムを実行するために使用できることを発見しました 。 C++テンプレートメタプログラミングは、ウォッシュされていない大衆にメタプログラミングをもたらし、 Blitz ++ライブラリ で数値メソッドを生成するなど、さまざまなことに使用しました。

37
Jon Harrop

さて、メタプログラミングは単なるプログラミングですが、基本的には "コードを書くコードを書く"です。

プログラムが独自の構造と動作を監視および変更できる場合に言及する機能は、リフレクションと呼ばれ、メタプログラミングの一種です。

動的に型付けされた言語には、これらの言語の解釈された性質によって可能になる強力なランタイムリフレクション機能があります...

静的型付き言語には、C++ template metaprogramming ...などの強力なメタプログラミング手法もあります。

28
CMS

これは私の個人的な意見であり、おそらくメタプログラミングの最もリベラルな定義です。

私はそれが含まれると思います:

  1. コンパイルコード生成またはランタイムコード生成(または両方)
  2. アスペクト指向思考またはアスペクト指向プログラミング
  3. [〜#〜] dry [〜#〜] 考える

これらのいずれかを組み合わせて使用​​すると、そこに到達できると思います:

  1. 反射
  2. DSL(ドメイン固有言語)
  3. 属性(.NET)または注釈(Java)
  4. ジェネリック(.NET/Java)
  5. テンプレート(C++)
  6. method_missing(Ruby)
  7. クロージャ/ファーストクラス関数/デリゲート
  8. AOP-アスペクト指向プログラミング
9
BuddyJoe

メタプログラミングとは、別のプログラムを出力するプログラムを作成することです。これは、LISPのような言語が本当に得意なものです。 Javaなどの言語よりも、Ruby、LISP、Schemeなどの実際のマクロ(C++マクロではなく、出力するコードを操作できるマクロ)をサポートする言語で行う方がはるかに簡単です。

1つの実装は、特定のタスクを達成するためにプログラミング言語を強化する方法である「ドメイン固有言語」を作成することです。正しく行われると、信じられないほど強力になる可能性があります。 Ruby on Railsはこの種のプログラミングの良い例です。

この方法の調査に興味がある場合は、 コンピュータープログラムの構造と解釈 を確認してください。

6
Steve Rowe

メタプログラミングとは、他のプログラム(またはそれ自体)をデータとして作成または操作するコンピュータープログラム、またはコンパイル時に行われる実行時に作業の一部を行うコンピュータープログラムの作成です。多くの場合、これによりプログラマーはすべてのコードを手動で記述するのと同じ時間でより多くの作業を行うことができます。また、再コンパイルせずに新しい状況を効率的に処理するための柔軟性をプログラムに与えます。 ( ソース 。)

基本的に、より多くのコードを出力するコードを作成し、それを実行して目標を達成します。これは通常、同じ言語(javascriptを使用してjavascript文字列を作成してからeval it)で行うか、別の言語を発行する(.NETを使用してWindowsバッチファイルを作成する)ことで行われます。

4
EndangeredMassa

wikipedia にはトピックに関する素晴らしい記事があります。メタプログラミングとしての資格を得るために、何かを実行時に変更する必要はありません。たとえば、多くの人がC++テンプレートを使用して、コンパイル時にメタプログラミングを行います。

4
Mr Fooz