
IOでのメタプログラミング
すばらしい言語ioに関する一連の記事の続きで、メタプログラミングについて書くつもりでした。
habrahabr.ru/blogs/crazydev/29375
habrahabr.ru/blogs/crazydev/28254
habrahabr.ru/blogs/crazydev/28167
habrahabr.ru/blogs/crazydev/28041
メタプログラミングとは、作業の結果として(または、特殊なケースとして、実行中に自分自身を変更または補完する)他のプログラムを作成するプログラムの作成です。
©正統派ウィキペディア
「メタプログラミング」という用語の標準的な意味はまったく面白くありません。IOライブラリを備えたチューリング完全言語は、あらゆる言語のプログラムのソースコードを生成できます。 さらに興味深いのは、プログラムの自己認識の可能性です。イントロスペクション、および実行プロセスにおける自身の生成と変更です。
ゴッドファーザーioを見ると、Lisp、Smalltalk、Self、およびその他の動的言語を見ることができます。 しかし、それらはすべて独自の方法でメタプログラミングの問題を解決します。たとえば、Lispはコンパイル中に非常に強力な部分であるマクロからコードを生成します。 Smalltalkには、オブジェクトのツリーを任意の方向にたどることができる「リフレクション」(リフレクション)の高度なシステムが含まれています。 Ioは、smalltalkの経路をたどり、構文の汎用性(Lispなど)ではなく、オブジェクトモデルに基づいて動的メカニズムを構築します。
内省
オブジェクトを探索するために、ioには、slotNamesメソッドなど、あらゆる種類の面白いことを実行できる多数のメソッドが用意されています。 オブジェクトにslotNamesにメッセージを送信すると、そのスロットのリストを取得できます。 さて、例えば:
Io>ロビーslotNames ==>リスト(「exit」、「Protos」、「forward」、「args」、「Lobby」、「launchPath」)
ご覧のとおり、このメソッドは通常のリストを返します。このリストで、foreachやその他のマップを使用してクロールできます。 まあ、原則として、あなたの心が望むものは何でもしてください。
同様に、オブジェクトプロトコルのリスト(protosメソッド)を取得できます。
Io>ロビープロト ==>リスト(Object_0x4191a0)
さらに興味深いメソッドはgetSlotです。これにより、実際に呼び出すことなくスロットの値を取得できます。 この調整により、古いメソッドに基づいてランタイムで新しいメソッドを作成できます(もちろん、それらをオンザフライで変更して、まったく異なるメソッドを取得できます)。 そしてもう少し考えてみると、この機能を使用して擬似遅延設計を作成できます。
Io> SampleObject:=オブジェクトのクローン ==> SampleObject_0x4461c0: タイプ= "SampleObject" Io> SampleObject m:= method( "Look ma、i can can fly!" Println) ==>メソッド( 「まあ、飛べる!」 println ) Io> SampleObject anotherM:= SampleObject getSlot( "m") ==>メソッド( 「まあ、飛べる!」 println ) Io> SampleObject anotherM ほら、飛べる! ==> maを見て、飛べます! イオ>
そして、完全に不自然なコードメソッドです。 正規化された形式で任意のメソッドのソースコードを取得できます。
Io>リストgetSlot( "map")コード ==> method(setSlot( "aList"、List clone); setSlot( "a1"、argAt(0)を呼び出す); if(a1 ==(nil)、例外発生(「引数がありません」)); setSlot( "a2"、呼び出しargAt(1)); setSlot( "a3"、argAt(2)を呼び出す); if(a2 ==(nil)、self foreach(v、setSlot( "ss"、stopStatus(setSlot( "c"、a1 doInContext(getSlot( "v")、call sender)))); if(ss isReturn、ss return(getSlot( "c"))); if(ss stopLooping、break); if(ss isContinue、continue); aList append(getSlot( "c"))); return(aList)); if(a3 ==(nil)、setSlot( "a1"、a1 name); self foreach(v、送信者setSlot(a1、getSlot( "v"))を呼び出します。 setSlot( "ss"、stopStatus(setSlot( "c"、a2 doInContext(呼び出し側、呼び出し側)))); if(ss isReturn、ss return(getSlot( "c"))); if(ss stopLooping、break); if(ss isContinue、continue); aList append(getSlot( "c"))); return(aList)); setSlot( "a1"、a1 name); setSlot( "a2"、a2 name); self foreach(i、v、呼び出し送信者setSlot(a1、i); 呼び出し送信者setSlot(a2、getSlot( "v")); setSlot( "ss"、stopStatus(setSlot( "c"、a3 doInContext(呼び出し側、呼び出し側)))); if(ss isReturn、ss return(getSlot( "c"))); if(ss stopLooping、break); if(ss isContinue、continue); aList append(getSlot( "c"))); return(aList))
これらの単純なメソッドを実際に使用すると、多くの
修正
ioのどのメソッドも、ioのシングルトンに戻る簡単な方法でオーバーロードできます。
シングルトン:=オブジェクトのクローン シングルトンクローン:=シングルトン
任意のオブジェクトの標準のcloneメソッドはそのオブジェクトのコピーを作成し(大体)、この場合、cloneメソッドはオーバーロードされて、オブジェクトの既存のインスタンスを返します。これはまさにシングルトンに期待されるものです。
io内のオブジェクトは、無制限に展開、変更、およびイントロスペクトできます。
(一般的に、半年前、メタプログラミングに関する記事を書き始めたとき、 lrrrとoleganzaは、io構文に関する通常のメソッド呼び出しをsqlクエリを使用して文字列に変換するsqlジェネレーターを作成しました。次のようになりました。
SQLGen select(*)from t_some_table t where where t.id = 42
結果はSQL文字列です。 しかし、私はソースをwきました、そして、これらの2つの悪鬼は、それに特別な価値がないと言いました(:
だから誰も動揺しなかった
まあ、それはおそらくそれです。 もっと書くことができますが、公式ウェブサイトwww.iolanguage.com/docsでマニュアルを掘り下げる方が良いです 。
psくしゃくしゃが起こった、頭痛、リリース後の月曜日。 怠azine、地獄、運命。 ごめんなさい しかし、何もないよりはましです(: