InfoQ

InfoQ

News

マイブックマーク

ブックマークするためにログイン または 会員登録 する

ブックマークされました!

ブックマークがエラーになりました。もう一度お願いします。

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

作者 Werner Schuster , 翻訳者 森田 秀幸 - (株)永和システムマネジメント 投稿日 2008年8月21日

セクション
デベロップメント,
設計/アーキテクチャ
トピック
Ruby ,
シンタックス ,
プログラミング ,
パフォーマンス&スケーラビリティ
タグ
メタプログラミング ,
LISP

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

特集コンテンツ一覧

GAE開発の落とし穴

Googleのクラウド環境をつかったGoogle App Engineによる開発するにあたり、初めての試みで苦悩する開発者達の経験をもとに、各開発フェーズにあわせて問題点やどう解決したかをご紹介します

イベントレポート:「Coqチュートリアル#1」

去る1月12日、定理証明支援系ツールCoqの初心者向けチュートリアルが開催さ れた(http://kokucheese.com/event/index/23667/)。今後も2月2日 (http://kokucheese.com/event/index/23744/)、2月9日、2月16日と引き続き開 催されていく予定である。本記事では、開催の様子をレポートする。

Javaの未来についてのNeal Gafter氏とのディスカッション

Choosing Options

Neal Gafter氏はOracleによるJava買収の影響に関する議論、Javaにセグメンテッドスタックやメタオブジェクトプロトコルを追加することについての主張、そしてJavaとC#との比較について話をしてくれた。

Google Dartのエッセンス:アプリケーションの構築、スナップショット、Isolate

GoogleはVMをともなう新しい言語であり、JSコンパイラでもあるDartをプレビューした。 InfoQはDartのアプリの構築に貢献する文法の裏側を探った:スナップショット、Isolate、モジュール方式

CSPベースのモデル検査ツール「Process Analysis Toolkit」

本記事ではCSPベースの「マルチドメイン・モデル検査ツール」である、PAT(Process Analysis Toolkit)について紹介する。モデル検査は、形式手法(Formal Method)という方法論を基礎とする技術であり、複雑さが増大しながらも安全性を求められる、現在のソフトウェア開発の状況に対する処方箋の1つとして注目されている手法である。

Jenkinsによる継続的インテグレーションのススメ(4) ~CloudBeesでJenkinsをサービスとして使う~

前回まで、Jenkinsの幾つかの側面に注目して解説をしてきました。シリーズ最後の今回は、Jenkinsをサービスとして使う方法を紹介します。

書籍『抽象によるソフトウェア設計-Alloyではじめる形式手法-』の紹介

Alloyは、MITにて開発された仕様記述言語であり、ツールによる自動解析を使い、インクリメンタルに形式仕様が書けることが特長である。筆者らはAlloy開発者による、Alloyを使った形式手法入門書を翻訳、今夏にオーム社より刊行した。本記事では、Alloyの簡単な概要と、翻訳書『抽象によるソフトウェア設計』(「Alloy本」)を紹介する。

Windows デバイスで開発するタッチユーザーインターフェイス

スマートフォンを中心としたマルチデバイスにおけるタッチユーザーインターフェイスへの対応は、既に必須の項目となりつつある。本記事では、Windows デバイスにおける UX のベースとなっている「メトロ」というデザイン言語を掘り下げながら、既存環境を意識しつつもどのようにタッチユーザーインターフェイス開発に取り組んでいくべきであるかについて解説していく。