1

たとえば、パターン「1..4」に続くすべての文字列を配列 [1,2,3,4] に変更するルールを実装できますか? JavaScript の場合:

//here you create a rule that changes every string that matches /$([0-9]+)_([0-9]+)*/
//ever created into range($1,$2) (imagine a b are the results of the regexp)
var a = '1..4';
console.log(a);
>> output: [1,2,3,4];

もちろん、ほとんどの言語では不可能だと確信しています。私の質問は、それが可能な言語はありますか? または、誰かがそのようなことを提案したことがありますか? このことには、グーグルで詳細を読むことができる「名前」がありますか?

4

4 に答える 4

3

CLOS(Common Lisp Object System)を使用すると、ライブオブジェクトを再定義できます。

最終的に、これを実装するには2つのことが必要です。

  1. 実行中のシステムのAST(抽象構文木)へのアクセス、および
  2. 実行中のシステムのオブジェクトへのアクセス。

メタオブジェクトプロトコルとそれらを使用する言語を調べてから、MOPとこれらのプログラムが実行される環境の両方の実装を調べます。

画像ベースのシステムは、変更するのが最も簡単です(たとえば、Lisp、場合によってはSmalltalk)。

イメージベースのシステムは、実行中のシステムのスナップショットを保存し、既存のオブジェクトとその定義を含む完全な環境の完全なシャットダウンと再起動、再定義などを可能にします。)

于 2012-09-04T20:48:07.550 に答える
3

はい。Common Lisp(および他の特定のLisp)には、ユーザーが入力ストリームと解析された実際の言語構造との間のマッピングを(増分的に)再プログラムできる「リーダーマクロ」があります。

http://dorophone.blogspot.com/2008/03/common-lisp-reader-macros-simple.htmlを参照してください

オブジェクトのレベルで操作する場合は、すべてのオブジェクトを追跡し、各評価ステップ(厄介な)でルールを処理するデバッグ/メモリ管理フレームワークを使用する必要があります。これは、smalltalkに靴べらをかけることができるようなもののようです。

于 2012-09-04T20:15:54.007 に答える
3

それ自体から言語を変更することは、リフレクションとメタプログラミングの傘下にあります。それは行動反射と呼ばれます。これは、言語レベルではなく、アプリケーション (クラス、メソッドなど) のレベルで機能する構造的リフレクションとは異なります。行動反射のサポートは、言語によって大きく異なります。

言語の変更は、大きく次の 2 つのカテゴリに分類できます。

  1. 言語自体のセマンティクス (つまりルール) を変更する変更 (たとえば、メソッド検索アルゴリズムの再定義)、
  2. 構文を変更する変更 (たとえば、配列を作成するための構文 '1..4')。

ケース 1 の場合、特定の言語は、メタオブジェクトと呼ばれる特別なオブジェクトを介して、アプリケーション自体の構造 (構造リフレクション) と実装の内部動作 (動作リフレクション) をアプリケーション自体に公開します。メタオブジェクトは、それ以外の場合は暗黙的な側面の具体であり、明示的に操作可能になります。アプリケーションはメタオブジェクトを変更して、その構造の一部または言語の一部を再定義できます。言語の変更に関しては、オブジェクト指向言語のコアメカニズムであるため、メッセージ送信/メソッド呼び出しの変更に通常焦点が当てられます。しかし、言語によっては、フィールド アクセス、同期プリミティブ、foreach 列挙など、言語の他の側面を公開するために同じ考え方を適用できます。

ケース 2 の場合、プログラムは、変更する適切なデータ構造で表す必要があります。Lisp ファミリーの言語の場合、プログラムはリストを操作し、プログラム自体をリストとして表すことができます。これはホモイコニシティと呼ばれ、メタプログラミングに便利です。したがって、Lisp に似た言語の柔軟性があります。他の言語の場合、その表現は通常 AST です。プログラムの表現を変換したり、書き直したりすることは、コンパイルまたはクラスのロード中に、マクロ、プリプロセッサ、またはフックを使用して可能です。

ただし、1 と 2 の境界線はあいまいです。構文の変更は、言語のセマンティクスを変更するように見える場合があります。たとえば、適切な getter と setter を使用してすべてのフィールド アクセスを書き換え、トランザクション メモリを実装するなどの追加ロジックを実行できます。フィールド アクセスとは何かという意味の変更を行ったのか、それとも単に構文を変更しただけなのか? また、線の間に落ちる他の構造もあります。たとえば、プロキシと#doesNotUnderstandトラップは、メッセージ送信の具体化をある程度シミュレートするための一般的な手法です。

Lisp と Smalltalk は、メタプログラミングの分野で非常に影響力がありました。次の 2 つのプロジェクト/プラットフォームは、それぞれの代表例として興味深いと思います。

  • Racket、言語内から言語を成長させることに焦点を当てた Lisp に似た言語
  • Helvetiaは、ホスト環境の AST を利用して新しい言語をホスト言語に埋め込む Smalltalk 拡張機能です。

私があなたの質問に実際に答えていなくても、これを楽しんでいただければ幸いです ;)

必要な変更を行うには、リテラルの作成方法を変更する必要があります。これは、通常、アプリケーションに公開されていない私の知る限りです。私が思いつくクローズドな作品は、Javascript に取り組んだVirtual Values for Language Extensionです。

于 2012-09-06T07:38:13.480 に答える
0

Ruby ではクラスを拡張できます。たとえば、この例では String クラスに機能を追加しています。ただし、クラスにメソッドを追加するだけではありません。メソッドを上書きすることもできますが、既に定義されているメソッドを定義します。alias_methodを使用して元のメソッドへのアクセスを維持したい場合があります。

これらすべてをまとめると、Ruby でコンストラクターをオーバーロードできますが、あなたの場合、落とし穴があります: コンストラクターが別の型を返すようにしたいようです。コンストラクタは、定義上、そのクラスのインスタンスを返します。文字列 "[1,2,3,4]" を返すだけの場合は、次のように簡単です。

class string
  alias_method :initialize :old_constructor
  def initialize
    old_constructor
    # code that applies your transformation
  end
end

しかし、必要に応じて配列を返すようにする方法はありません。

于 2012-09-04T20:19:08.460 に答える