BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース メタプログラミング 総括: 速度、Ruby マクロ、スクリーンキャスト

メタプログラミング 総括: 速度、Ruby マクロ、スクリーンキャスト

ブックマーク

Matt Aimonetti 氏は(リンク) 最近メタプログラミングの速度(リンク)、特にメソッドを定義する様々な方法の速度をよく調べていた。そして彼は、ユーティリティメソッドを定義するための Proc オブジェクトを用いた define_method を使ったコードが、静的に定義されたメソッド(つまり def method_name のように定義されたメソッド)よりもずいぶん遅いことに気づいた。しかしながら、補足記事で、Matt 氏は速度に違いが出る理由とその解決方法を(リンク)見つけた。それは以下のようなものだ。

今日 Wycats 氏がこの投稿に対して反応をしてくれ、問題は define_method であり、class_eval は普通のコードと同等に動作し、class_eval は eval.c の中で普通の Ruby コードのように評価されることを教えてくれました。一方、define_method は proc にマーシャルする必要があります。

Matt 氏は以前 class_eval を使ってベンチマークを取ったコードの修正バージョンを提供しており、現在それは静的なメソッド定義を使った早いコードのように動作している。メタプログラミングを利用する際に覚えておくと少し役立つ情報といえる。

メタプログラミングスペクトルの他の終着点に、Reginald Braithwaite 氏(リンク)の Rewrite gem (リンク)がある。Rewrite gem は LISP もしくは Scheme のような言語で備えられた、マクロもしくはマクロ展開と呼ばれるアプローチを利用している。Ruby において、このアプローチは(わずかながら)言語の外側での手続きが必要となる。通常の Ruby コードは、「ロードされた Ruby コード」を表現しているモノに対するアクセス方法を持っていない。リフレクションはメソッドボディレベル程度に留められているのだ。Ruby コードにアクセスするために、つまりは抽象構文木を Ruby インタプリタから取得するために、MRI 1.8 では ParseTree 拡張が使われる。Rubinius では ParseTree S式がサポートされており(例えば Debugger はメソッドの S式に対するアクセスを許可している)、また、JRuby 用の不完全なバージョンの ParseTree も存在する(メソッドのある形式から AST へアクセスするためのサポートが欠けている)。ParseTree は Ruby 1.9 には対応していない。

Rewrite gem は現在、その実体として、ある部分的な問題の解決のために使われているが、そのなかの原則は一般的に利用できるものとなるだろう。いま解決しようとしていることは、クラスへメソッドを追加する(Open Class)問題だ。そのクラスの問題は変更がグローバルに行われることにある。もし一つのコード片が foo と呼ばれるメソッドを Object に追加すると、実行環境上のすべてのコードにもこのメソッドが見えるだろう。それは、もし他のコード片が同じ名前で同じ名前のクラスにメソッドを追加すれば、名前衝突のような問題の原因となりうる。

その問題は Rewrite gem で解決されている。ブロックのスコープに対し、追加されたメソッドの可視性に制限を設けるのだ。それはここで見ることができる(リンク)

with(andand) do
 foo().andand.bar(blitz())
end

with メソッドに渡されたブロックの中のコードは、ParseTree S式に置き換えられ、解析され、書き換えられるようになっている。今回の場合、さまざまなクラスから呼ばれるような andand メソッドは存在しない。それどころか、with メソッドはこのメソッドを呼ぶコードを探し、それが期待する振舞いを返すように書き換える。

Rewrite gem で実装されたこのアイディアが Ruby におけるマクロを使った試みであること、そしてより多くのアイディアが想像できるということは、心に留めておくべき重要なポイントだ。Ruby の便利なブロック文法は、様々なことを簡潔に表記するのを実現させてくれる一方で、遅延して評価可能な複数のコード片を渡すことはより難しくなり、Proc を生成する、更に冗長なメソッドを必要としている。

マクロのようなコンセプトを導入するにあたり、始めるのによい機会として "Practical Common Lisp"(リンク)(邦訳: 実践 Common Lisp)がある。コードを解析するために ParseTree を利用している他のプロジェクトもある。InfoQ は、ParseTree を使う Sequel と merb がいかに野心的であるかを紹介している(参考記事・英語)。マクロと lambda の中間あたりに位置している lazy-lambdas として言及された Joel Klein 氏のディスカッションも見てほしい(リンク)

最後、Ruby におけるメタプログラミングの可能性に対してあまり馴染みのないすべての方のために、Dave Thomas 氏 (PragDave) (リンク)によるスクリーンキャストの新シリーズがそのコンセプトの扉に導いてくれている。スクリーンキャストシリーズは Antonio Cangiano のレビュー(リンク)や Mike Riley のレビュー(リンク)など、いくつかのレビューで既に好評をえているものだ。

原文はこちらです:http://www.infoq.com/news/2008/07/metaprogramming-roundup

この記事に星をつける

おすすめ度
スタイル

BT