MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第321号

2008-11-25

目次

  • りんご味Ruby         第36回  藤本 尚邦
  • 藤本裕之のプログラミング夜話   #149
  • 高橋真人の「プログラミング指南」  第147回
  • mosa entranceだより       第1回   大野 亮一郎

りんご味Ruby   第36回  藤本 尚邦

前回に引き続き、Rubyでの構文糖衣(syntax sugar)やDSL(Domain-SpecificLanguage=ドメイン固有言語)の作り方について、今回は、アクセッサを宣言するための疑似的な構文糖衣をどのように実現するのか、そのいくつかの方法を見ていきます。

真偽値を返すアクセッサを宣言するための(疑似)構文糖衣 attr_predicate を使えるようにする方法としては:

 ・クラス継承             – 構文糖衣を実装した親クラスを用意
 ・ミックスインモジュール — 構文糖衣を実装したモジュールを用意
 ・オープンクラス         – Moduleクラスに直接、構文糖衣を実装

の3つの手段が考えられます。

■ クラス継承 — 構文糖衣を実装した親クラスを用意

これは、attr_predicate をクラスメソッドとして実装した親クラスを定義しておき、その派生クラスの定義で attr_predicate を使えるようにする方法です。

--------------------------------------- attr_predicatable_class.rb ---
class AttrPredicatableClass
 def self.attr_predicate(*names) # 構文糖衣をクラスメソッドとして定義
   names.each do |name|
     define_method("#{name}?") do
       instance_variable_get("@#{name}") ? true : false
     end
   end
 end
end
----


親クラスを定義したライブラリを作ってしかるべき場所に置いておけば、そのライブラリをrequireでロードして、派生クラスの定義中で attr_predicate を使えるようになります:

require 'attr_predicatable_class'

class TodoItem < AttrPredicatableClass   # 派生クラスの定義
 attr_reader    :summary
 attr_predicate :done                   # 新しい構文糖衣を使用
 attr_writer    :done

 def initialize(summary)
   @summary = summary
 end
end

■ ミックスインモジュール -- 構文糖衣を実装したモジュールを用意

attr_predicate を実装したミックスインモジュールを定義しておけば、あるクラスの定義のときに、includeを使ってそのミックスインモジュールを組み込むことにより attr_predicate が使えるようになります。

---------------------------------- attr_predicate_attachment.rb ---
module AttrPredicateAttachment
 def self.included(target_class)
   def target_class.attr_predicate(*names)
     names.each do |name|
       define_method("#{name}?") do
         instance_variable_get("@#{name}") ? true : false
       end
     end
   end
 end
end
----


クラス継承の場合と同様に、このライブラリをrequireでロードすると、クラス定義のときにモジュールを組み込んで attr_predicate を使うことができます。

require 'attr_predicate_attachment'

class TodoItem
 include AttrPredicateAttachment  # ミックインモジュールを組込み
 attr_reader    :summary
 attr_predicate :done             # 新しい構文糖衣を使用
 # 以下略
end

AttrPredicateAttachmentモジュールの定義でのポイントは

 def self.included(target_class)
   def target_class.attr_predicate(*names)
     ...


のところで、「AttrPredicateAttachmentモジュール自体」に included というメソッドを定義していることです(このselfは「AttrPredicateAttachment モジュール自体」を指します)。

あるクラスの定義で include によりモジュールが組み込まれたとき、その「クラス自体」を引数(つまり仮引数target_classの値)として、組み込まれたモジュールのincludedメソッドが呼び出されます。上記のTodoクラスの定義の例では:

 include AttrPredicateAttachment

のところで、AttrPredicateAttachmentモジュールのincludedメソッドが呼び出されます。このとき「Todoクラス自体」が仮引数target_classの値となりますから、Todoクラスのクラスメソッドとして attr_predicate が定義されることになります。定義の中身はクラス継承の場合と同じですね。

ということで、AttrPredicateAttachment を include したクラスの定義ではattr_predicate が使えるようになるわけです。

以上の2つは、能動的にクラス継承したりモジュールを組み込まない限り使えないという点で、わりと安全で行儀のよい実現方法といえるのですが...

■ オープンクラス -- Moduleクラスに直接、構文糖衣を実装

最後にオープンクラス。Rubyでは既存のクラスを実行時に直接変更することができるのですが、そのことをオープンクラスといいます。とても強力で上手に使えば有効な一方で、乱用しすぎると混乱のもとにもなるという、まさに「諸刃の剣」なのですが、Rubyの重要な特徴といえます。ということで次回に続きます。

藤本裕之のプログラミング夜話 #149

 前回、映画「ファイナル・ファンタジー」を例にひいたが、あそこまで(つまりフルCGアニメーションでゲームの世界を再現するとこまで)やらないまでも、ゲームを「原作」とした映画がたくさん撮られるようになり、ある種のコンピュータゲームはその制作のしかたというか、その体制が非常に映画に似かよって来ている。

 若い人にはまたオジサンが昔話を始めたと言われそうだが、初期ののコンピュータゲームなんて、プログラマが自分で設計しシナリオを書き、シコシコとドット絵でキャラクターを描きプログラムを作りデバッグもテストもあれもこれも全部ひとりでこなして月刊アスキーにプログラム・ソースを投稿する、みたいなもんだったのだ。

 それがいまや、「インテジャーって何?」てな顔した(多分に偏見が入ってますな)ゲーム・プランナーとかいうヒトが「ローマ時代と古代中国をミックスしたみたいな文明がいちど滅びたあとの荒涼とした近未来世界でファンタスティックかつキッチュなキャラクターたちがドラゴンボールZ的にフィジカルかつエネルギッシュなバトルを繰り広げるんだよ」みたいなワケワカメのコンセプトを語ってさ、それを猟師が鉄砲で撃ってさ、煮てさ、焼いてさ……なんでとつぜん「あんたがたどこさ」になってんだかわからんが、マンガ家だったりイラストレイターだったりがキャラクターデザインをし、CG作家がそのモデルを起こし、ユーザーの操作に応えてそいつらがすべったり転んだりするコードをプログラマが書くという……プロダクション・システムというものが確立
している。

 そうなるとなにが起きるか。1人で作ったもんであれば、その1人が食えるだけのお金を生めばまぁいいわけなんだが、100人で作ったもんは100人が食えるだけの利益を生み出す必要が産まれてくるのである。が、ゲームというものは映画以上に、コケた場合にはそれこそ徹底的にまったく全然金輪際これっぽちもお金にならないのである。

 前回書いたように映画であれば、あの「デビルマン」だってDVDを買う奴がいるのだし、もう少しほとぼりが冷めれば(我ながらなんて言い方だ)原作を読んで感動した少年が不幸にもTSUTAYAの棚であれを見つけてレンタルするかも知れない。またはこれから十数年先、かつてオレたちが産まれる前の「ゴジラ」や「ラドン」をそういう機会に観たように、あれを夏休みの午前中に「お子様映画劇場」みたいな形で放映するTV局がないとも限らない。さすればあんな映画でもそのときドキごとにいくばくかのお金を産む。

 ところがゲームはそうではあるまい。ゲーム好きの人は思い出して欲しい、ゲームに興味のないヒトは近くのゲーム好きに聞いてご覧なさい。史上、いったん「クソゲー」(それにしてもまぁとことん思いやりのない表現だよな)という烙印をおされたゲームが再評価などされたことはない。リサイクルショップでも買い取ってもらえず、なんとか不良在庫を整理しようと人気のあるゲームと抱き合わせ販売でもしようもんならあっというまに非難のまととなる。そしていつしかツワモノどもの夢の後、そのゲームがターゲットとしていたゲーム機自体が新しいものにとって代わられ忘れ去られる。もう一度書くが、それこそ徹底的にまったく全然金輪際これっぽちもお金にならないのである。

 先般(実はこれを書いてる時点では昨日なんだけど)、文化庁がやってる文化審議会著作権分科会の専門委員であったジャーナリストの津田大介氏の話を聞く機会があったんだが、興味深かったのは彼の「著作権問題を考える場合、『コンテンツに永続性がない』ってことを考えなければならない」という認識だったの。どういうことかというと、例えばかつてオレがビートルズのLPを買ったとき、オレは「音楽」を買ったのか塩化ビニルのレコードを買ったのかってことである。

 オレが買ったのが音楽だっていうのなら(JASRACが著作権料を請求するのはその立場からだ)、なんでオレはLPが聴ける環境を失ったときもういちどCDを買わなければならなかったの? つまりコンテンツの永続性がメディアによって阻害されているぢゃないかと。それでもビートルズなら必ずCDが出るからいい。かつてオレが持ってた上田正樹のソロ・デビュー盤「上田正樹」、セカンドアルバム「PUSH & PULL」、3枚目の「NO PROBLEM 」などは待てど暮らせど
CDにならず……あ、個人的恨み言はいいか。……で、コンピュータゲームってのは、この「メディアによる永続性の阻害」ってのを宿命的に被るコンテンツなんだよな。(以下次回 2008_11_22)
                       

高橋真人の「プログラミング指南」第147回

プログラマのためのオブジェクト指向再入門(53)

〜XcodeによるPowerPlant X入門(36)〜

 こんにちは、高橋真人です。
 前回、アタッチメントオブジェクトが消滅するタイミングで、アタッチメントによりインストールされていたイベントハンドラが取り除かれるのだが、それはそもそもどこにあるのか? という疑問を提示しました。
 その際に、「いくら探してもそのようなメンバ変数はありません」と言いましたが、これは誤りでした。確かに継承元のいずれのクラスにもそのようなメンバ変数はないのですが、そんなところを探さずとも、MyViewAttachmentクラス自体の中にちゃんとmEventHandlerというメンバ変数が用意されていたわけです。
 「うっかり見落とした」と言い訳したいところなのですが、実のところ、このメンバ変数がないと、これから行う説明が成り立ちません。そんなわけで、私のミスリードにより混乱させてしまったことをお詫びします。

 さてこれからお話しするのは、そんなアタッチメントも含めた、PowerPlantXにおけるイベントハンドラの取り扱い方についてです。アタッチメントの話を始める時にもお話ししたように、PPxではCarbonイベントのハンドリングが重要な位置を占めます。そもそもPPxが対象とするモダンなCarbonプログラムでは、Carbonイベントの取り扱いが中心となってプログラムが構成されますから、当然と言えば当然のことです。
 ただ、“生の状態”でCarbonイベントを取り扱う通常のCプログラムとは違って、PPxではオブジェクトの中にこれらの仕組みを包み込むことで、管理しやすくしています。実際、少し前に時間をかけて説明したViewのサブクラス化によるカスタマイズにおいても、Carbonイベントのハンドリングは大きな部分を占めていたわけですが、イベントハンドリングの細部がオブジェクトによ
り包み隠されていたために、あまりこれらの部分を意識することなくカスタマイズできていたわけです。
 PPxにおけるイベントハンドリングの中核を担うのが、PPx::EventDoerというクラス(これは、PPx::ControlDrawDoerとか、PPx::SpecificEventDoerなどの大元のクラスです)です。私たちは単にこれらのサブクラスを作成し、DoXxxxx()関数を実装してInstall()関数を呼ぶだけで、あとはこれらのオブジェクトがよきにはからってくれたのです。
 そこで、それらのオブジェクトの内部動作を探ってみようというのが、これからのお話です。

 では、PPxがCarbonイベントをどのように扱っているのかを見る前に、通常のCプログラムにおけるCarbonイベントの扱い方を簡単におさらいしておきます。以下はイベントハンドラのインストールの部分です。

EventHandlerUPP upp = NewEventHandlerUPP(EventHandlerProcName);
EventTypeSpec typeList[] = {
   { kSomeEventClass, kSomeEventKind }
}; 
InstallEventHandler(target, upp, 1, typeList, NULL, NULL);


 まず、このコードが実行されるのに先立って、イベントハンドラの実体となるコールバック関数が定義されていることが前提となります。NewEventHandlerUPP()という関数は、このコールバック関数(以下「ハンドラの関数」と呼びます)の名前(ここでは、EventHandlerProcNameとなっています)を引数に取って、新たにUPPというものを生成して返します。
 UPPとは何でしょうか? 「UPPというのはUniversal Procedure Pointerの略で...」と説明していってもいいのですが、それに時間を割くほどの意味をここでは見いだせません。理屈として、UPPはハンドラの関数を間接的に指す“中間ポインタ”のようなものですが、現時点では“歴史的な事情で存在する”程度のものでしかなく、例えば、いまの私の手もとの環境(Mac OS X10.3
on PowerMac G5およびMac OS X 10.5.5 on MacBook)では、NewEventHandlerUPP()に渡されるアドレスと、この関数が返すアド レスは同じ値です。理屈的に言えば、新規にメモリ領域を確保してオブジェクト を生成するはずなのですが、今のところ単に受け取ったポインタを型を変換して 返しているにすぎないわけです。

 環境が変われば違いが出るのかもしれませんが、とりあえずキャストして型を変換するだけでも結果に違いはないように思います。とは言え、AppleのドキュメントにはUPPを使うように書かれていますし、PPxもそれを踏まえて処理をしていますから、ここでは建前通りに、あたかもUPPというモノが作られていると考えてください。
 そして最後に、EventHandlerです。InstallEventHandler()というAPI関数に、ターゲット、UPP、そしてどんなイベントが発生した時にコールバックを呼び出すのか、などの情報を与えます。“どんなイベントが”という部分は、上記のコードではkSomeEventClassとkSomeEventKindという架空のEvent ClassとEvent Kindの組み合わせにしています。この辺も過去の連載で説明してあるので、分からない方は過去記事を参照してください。
 ところで、EventHandlerと呼んでいるのは便宜的なものです。常識的に考えれば、イベントハンドラは上記のハンドラの関数のことを意味するように思えますが、ここではコールバックを上記の設定で“登録した情報”が、それの意味するところとなります。

 重要なので改めて確認します。ハンドラの関数、UPP、そしてEventHadlerがここで重要な3つの要素です。あくまで呼び方は便宜的なものですから、その意味するところをしっかりと意識しておいてください。
 さて多くのプログラムでは、これらの要素がプログラムの実行中ずっと存在し続けます。C/C++では関数の定義を動的にすることはできませんから、ハンドラの関数は最初から最後までずっと存在します。あとUPPとEventHandlerは、多くの場合、プログラムの初期化の過程で生成されて、そのままプログラムが終了するまでの間、ずっと存在し続けます。
 そういう一般的なケースでは問題ありません。ところが何らかの事情で特定のハンドラが一時的にのみ必要とされることがあります。今も話題にしているアタッチメントのようなケースも一例です。この場合、前述のように一時的なものとはできないハンドラの関数を除く、UPPとEventHandlerを一時的に作り、役割が終わった時点で始末するという形になります。

 さて、通常のCプログラムにおいて、上記を実現するのはちょっとだけやっかいです。でも、実現は可能です。まずEventHandlerですが、これを始末する、つまり登録情報を抹消するのはRemoveEventHandler()というAPI関数です。この関数に渡す値は、EventHandlerRefという、EventHandlerへのポインタなのですが、この値はどこから取得できるのでしょうか?
 実は、前述のコード例でNULLになっている、InstallEventHandler()の最後の引数に対してEventHandlerRef型の変数のアドレスを渡してやると、作成されたEventHandlerのポインタが受け取れます。ですから、プログラムのどこかにこの値を保存しておいて、RemoveEventHandler()に渡してやればいいわけです。
 UPPについては、既に変数に値が取れていますから(上記のコードでは、upp)これもどこかに保存しておけば、あとでDisposeEventHandlerUPP()というAPI関数に渡して始末することができます。
 問題は、これらの値をどこに保存しておくか、です。
 Cのプログラムであれば、おそらくグローバル変数に保存しておくことになるでしょう。プログラムの構造を巧妙に作り込めば、これらのデータを無闇に晒すことなく保管しておくことも可能かもしれませんが、できることならこれらが一まとまりで管理できるとラクでいいですよね。

 このように、後始末をする際にちょっとした面倒臭さが発生するというのが、ここで問題にしたいことです。では、PPxではこの辺をどう解決しているのでしょう? それを次回は見ていきたいと思います。

mosa entranceだより       第1回   大野 亮一郎

MOSA会員の皆様こんにちは! mosa entranceという集まりを主催しております大野と申します。
この度MOSA伝の場をお借りして、mosa entranceの活動をお伝えすることになりました。少しでも多くの皆様にこの企画を楽しんで戴けるような報告ができればと思っています。どうぞよろしくお願い致します。

mosa entranceの主旨についての説明は、ぜひ初回のご案内http://www.mosa.gr.jp/?p=1973をご覧ください。簡単に申し上げますと、MOSA会員が交流する「場」を準備
し、孤独なプログラミング(笑)を楽しくすることがひとつの目的です。特に悩めるプログラミング初学者の方に、ステップアップのお役に立てて戴きたいと考えています。

さて、いつもの活動レポートは主催者の視点でお伝えしておりましたので、ここでは一参加者としての感想を述べさせていただこうと思います。参加してみて一番納得したのは、やはり皆さんAppleの製品をお好きなのだという当たり前のことでした。同時にMac OSだけでなくコンピュータに関する幅広い知識をお持ちの方が多いということ。私自身も仕事ではWindowsやその他のOSに触れる時間の方が長いのです。ましてやWebアプリケーションの開発に携わっていらっしゃるなら環境を選んではいられませんから、幅広い知識が前提になるわけですね。

次にプログラミングに取り組むといっても様々な環境があるということ。開始時に簡単な自己紹介をしていますが、皆さんプログラミングとの関わり方が違います。ご自分で会社を経営し、Macを中心に開発なさっている方、企業内で開発されている方、普段はWindowsが中心で、Macは趣味的にされている方、Webアプリケーション開発をされている方、デザイン中心の方、またプログラ
ミングはあくまで趣味としてされている方…。業界も様々で、全く異なる背景をお持ちの方がMOSAにいらっしゃることがよくわかります。mosa entranceの場で実際に皆さんとお会いすることが非常に刺激になっています。

mosa entranceでは、もちろんプログラミング技術に関する話題が一番多く、ちょっとした余談でさえ非常に高濃度の肥やしになることが実感できます。しかし、それ以上に皆さんから直接得ることのできる、空気の様なものが大いに自分を奮い立たせてくれます。時として辛くなるのがプログラミングですが(え? 辛いことばっかり?)、そんな壁にあたっても乗り越えられるエネル
ギーを得ています。特に私をはじめとする初学者の者にとっては、これが本当に大切なことなのではないでしょうか。

まとまりのない文章でお恥ずかしい限りですが、これが一参加者としての私の感想です。
MacやiPhoneでプログラミングを楽しみたいとお考えの皆様、是非一度mosa entranceにお寄りください。セミナーでお会いするMOSAの皆様とはひと味違う雰囲気を感じてみてはいかがでしょうか。お気軽に、お時間の許す範囲でお立ち寄りください。どうぞお待ち申し上げて
おります。

次回のmosa entrance便りは、実際にご参加戴いた方にバトンタッチしてお話し戴く予定です。
どうぞお楽しみに!

★大野さんのプロフィールは上記初回のご案内にあります
http://www.mosa.gr.jp/?p=2260

◇MOSAからのお知らせと編集後記は割愛します◇

 

 MOSA Developer News   略称[MOSADeN=モサ伝]
        配信停止 mailto:mosaden-ml@mosa.gr.jp
 記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
      記事投稿受付 http://www.mosa.gr.jp/?page_id=850
Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
特定非営利活動法人MOSA  http://www.mosa.gr.jp/
Copyright (C)2007 MOSA. All rights reserved.