2008-03-04
目次
りんご味Ruby 第20回 藤本 尚邦
MacRubyというRuby処理系が公開されました。ということで、今回は予定を変更してMacRubyを概観します。MacRubyの特徴としては:
・すべてのオブジェクトがNSObject
・文字列・配列・ハッシュのリテラル
・メソッドの定義・呼出のための拡張構文
・Ruby 1.9ベース
・処理系に組み込み
・GCがObjective-C側のGC
などたくさんありそうなのですが、目に留まったところを見てみます。
■ すべてのオブジェクトがNSObject
MacRubyでは、クラス階層構造の頂点にNSObjectクラスがあります。RubyのオブジェクトはすべてObjectクラス(およびその派生クラス)のインタンスなのですが、そのObjectクラスがNSObjectクラスからの派生クラスになっています。
・Ruby 1.8では: Object < ...
・Ruby 1.9では: BasicObject < Object < ...
・MacRubyでは: NSObject < Object < ...
このようなクラス階層構造により、すべてのRubyオブジェクトをNSObjectとして扱うことができ、Rubyプログラムで定義されたクラスもすべてNSObjectクラスの子孫となります。
irb> class Hoge
end
irb> Hoge.ancestors
=> [Hoge, Object, NSObject, Kernel]
irb> Hoge.is_a? NSObject
=> true
(注) KernelはすべてのRubyオブジェクトにincludeされるモジュールです
(注) ancestors は、すべての先祖クラスとincludeしたモジュールの配列を
返すメソッドです
RubyCocoaでは、必要になったときにRubyのオブジェクトをObjective-Cのオブジェクトに変換していますが、MacRubyではRubyのオブジェクト=NSObjectでもあるので、変換する必要がないということになるでしょう。
■ 文字列・配列・ハッシュのリテラル
MacRubyでは、String(文字列)、Array(配列)、Hash(ハッシュ)クラスが、それぞれ、NSString,NSArray,NSDictionaryからの派生クラスになっています。
Rubyでは文字列、配列、ハッシュをリテラルとして記述できますから、これはつまり、MacRubyではNSString, NSArray, NSDictionaryをリテラルで記述できるということになります。
irb> "りんご味Ruby".class.ancestors
=> [String, Comparable, NSString, Object, NSObject, Kernel]
irb> [ "りんご", 12345, "これは配列" ].class.ancestors
=> [Array, Enumerable, NSArray, Object, NSObject, Kernel]
irb> { "りんご"=>"apple", "味"=>"flavor", "Ruby"=>"Ruby" }.
class.ancestors
=> [Hash, Enumerable, NSDictionary, Object, NSObject, Kernel]
上の配列リテラルの例では、NSArrayであるはずの配列の要素に、数値リテラルが含まれています。NSArrayの要素には、Objective-Cオブジェクトしか置くことができないので、Objective-C言語ならば、NSArrayの要素に数値リテラルを入れることはできません。しかし、Rubyでは数値リテラルもオブジェクトですから、MacRubyにおいては数値リテラルがNSObjectということになります。したがって、NSArrayであるはずの配列リテラルに数値リテラルを置くことができるわけです。
■ メソッドの定義・呼出のための拡張構文
Rubyでは、キーワード付き引数の代用としてHashがよく使われています(Ruby on Railsなどで多用されています)。MacRubyでは、Objective-Cのキーワード付きメソッドの定義と呼出のために、一歩踏み込みRuby言語の構文を拡張しています。これは、Rubyプログラミングでよく使われる実行時の疑似構文による拡張ではなく、処理系のパーサ(構文解析器)自体を直接変更しています。
キーワード付きメソッドの定義例:
def outlineView outlineView, numberOfChildrenOfItem:item
item ? item.numberOfChildren : 1
end
キーワード付きメソッドの呼出例:
window = NSWindow.alloc.
initWithContentRect( frame,
styleMask: NSBorderlessWindowMask,
backing: NSBackingStoreBuffered,
defer: false)
この拡張構文はObjective-Cのための構文といえるので、プログラムの中では、WindowsやLinuxなど他の環境で使うことを考慮する必要のないところでのみ使うようにした方がよさそうです。
■ 実装はRuby 1.9 ベース
現時点でのMacRubyは、Ruby 1.9のソースコードに対して、オブジェクトシステムやガベージコレクタに変更を加えた形で実装されています。
RubyCocoaは、Ruby処理系のソース自体には手を加えず、実行時にObjective-C対応の変更を加えるライブラリとして実装されています。それに対して、MacRubyは、Ruby 1.9のソース自体を積極的に変更して、処理系のビルド時にRubyのオブジェクトシステムにObjectve-C対応を組み込んでいます。
■ RubyCocoaとの関係
RubyCocoaとMacRubyと2つあってややこしいとか、どっちを使えばいいのかなと思われるかもしれません。基本的に用途はほとんどかぶっているので、ユーザとしてはひとつに統一してほしいところです。現時点でのMacRubyは開発まっただ中でまだまだ動かないところもあるようですが、完成度が高まるにつれてMacRubyに移行していくことになるでしょう。
今回は、私もMacRubyを試してみたばかりで勘違いしていることもあるかもしれないのですがその点ご容赦ください。
■ 参考URL
MacRuby
http://trac.macosforge.org/projects/ruby/wiki/MacRuby
Objective-CベースのRuby実装「MacRuby」が登場(海上さんの記事)
http://journal.mycom.co.jp/news/2008/02/29/021/index.html
藤本裕之のプログラミング夜話 #133
前回まで、Macに限らずPCに限らずパーソナルコンピュータの普及は進み、いまやウチにパソコンがない人のほうが珍しい……ってことはないのかな、とにかくオレが最初のMacを買った頃に比べたら絶対的にとんでもないことになっているのに、その割にソフトウェアが売れないのはパソコンの使い方が違うのぢゃないか、という話をしてきたわけだが、この辺でそのヨタ話の地歩をちと固めてみたい。……つうかちょっとだけ調べてみたんだけどね。
内閣府がやってる「消費動向調査」というのがあって、これは調査対象が2人以上の日本人世帯、つまり「イヌと外国人はお断り」……ぢゃなかった「独身者(シングル)と外国人の買うものなんかはどうでもいい」という、ちょっとどうかと思うような調査だったんだが(最近のでは単身世帯は入ってる)、ともかくそれによると1987年3月の段階でパソコンの普及率は11.7%であった。翌88年はなぜか減って9.7%、89年が11.6%と、この時期は調査対象世帯をランダムに選ぶことによって生じる誤差を考慮すればだいたい11%くらいだったわけだ。パソコンは10軒に1台、これって自家用車に比べてどうなんだろうって数字だよね。
この数字が変化の兆しを見せるのは1994年。この年数字が13.9%、Windows95が出た翌年が15.6%、以降2005年に前年の65.7%から64.6%とわずかに下がるが、2006年には68.3%と盛り返し、昨年3月には遂に71.0%と初めて70%を超えた。やれ人口が減ってますとかパソコン市場はケータイに食われてますというが、実に10軒に7軒がパソコンを保有しているのであり、冒頭にオレが書いた「いまやウチにパソコンがない人のほうが珍しい」ってほどではないものの「ない人の方が少数派」という情勢ではあるわけである。
こうなってみると当然「ほんぢゃそのパソコン所有者の人たちはたとえば年にいくらくらいソフトウェアにお金を使うのよ?」という辺りを知りたくなるが、残念ながら内閣府ではそういう調査はやっておらず、また結構一所懸命探したつもりなのだが民間でもそういう調査をやってるところはないみたいなので、ちょっと目先を変える……というかからめ手から攻めてみる。つまり「ほんぢゃそのパソコン所有者の人たちはパソコンを何に使っているの?」と。ね、こっちの調査だったらどっかにありそうな気がするでしょ。
ちうわけで「パソコン 用途 調査」の三題噺……ぢゃなかった三要素でググってみるとありましたありました。「ネットワークと国民生活に関する調査」調査報告書というpdf文書。これの「情報通信機器の利用状況」の中にそのものズバリ「パソコンの用途」という調査結果を発見した。アメリカと日本、そして韓国のパソコンユーザーに
(1)テレビ番組を見る
(2)テレビ番組を録画する
(3)ビデオを編集する
(4)デジカメ画像を編集する
(5)DVDを視聴する
(6)音楽を聴く
(7)音楽を編集する
という選択肢を示し、自宅でのパソコンの用途を複数選択可で訊きました、というもの……っておい、そもそもこれしか選択肢がないのか、と思ってしまうが、興味深いのは日本人ユーザーの用途の1位がアメリカ人、韓国人のそれと違うことである。なんだと思います? 日本人のトップは「デジカメ画像を編集する(58.2%)」なんだけど、米韓の1位は「音楽を聴く」なんである。あ、なるほど一時「あるのはデジカメ付属ソフトの仕事だけ」みたいな状況だったもんね。……ちうか、そうなのである。これってほとんどMacやPC(とデジカメ?)買えばその日からできちゃうことばかりではないか。
とにかくそういうことなので、オレの「パソコンが普及したわりにソフトウェアがそれに比例して(別に比例まで望んでないのにさ)売れてないのはなんでだ」という疑問というか問題意識にはちゃんと根拠があるということが確認できたわけだ(できたでしょ?)。次回からは「なんでだ」の中身を掘り下げつつ「それをなんとかすることができるんだろうか」という方向に話を進めて行きたい(もんである)。
(以下次回 2008_02_29)
高橋真人の「プログラミング指南」第131回
〜XcodeによるPowerPlant X入門(20)〜
こんにちは、高橋真人です。早速、前回のコードの解説をします。
今回のプログラムで目新しい部分はPPx::Viewの拡張です。それについてはあとで説明しますが、その前に今回“ついで”に加えた新しい部分を説明してしまいましょう。
MyApplication.cpのウインドウを生成する部分で、Windowの生成直後に以下のようなコードがあります。
if (theWindow) {
PPx::View *contentView = theWindow->GetContentView();
HIRect contentFrame;
contentView->GetLocalFrame(contentFrame);
HIRect frame = CGRectOffset(
contentFrame, 20.0, contentFrame.size.height - 60.0);
frame.size = CGSizeMake(120.0, 40.0);
MyView *view =
PPx::CreateView
ボタンとして機能するMyViewのための矩形(frame)を、前回のような決め打ちの値にせず、ウインドウの位置から割り出して左下に配置されるように調整してあります。コード量を減らすために少し変な書き方になっていますが、以下のように書いてももちろん同じことです。
HIRect frame = CGRectMake(
20.0,
contentFrame.size.height - 60.0,
120.0,
40.0);
PPx::CreateView
それでは、拡張したMyViewの解説です。表示されている青い四角(これが、MyViewのインスタンス)をマウスでいじってみると、ボタンと同じように動作することが分かるはずです。
MyView上でマウスボタンを押すと、青い色が濃くなります。そのままマウスボタンを放すとボタンをクリックしたことになり、「Clicked」というアラートが表示されますし、ボタンを放さずにポインタをMyViewのエリアから出すと、青い色が最初の状態に戻ります。もちろんそのままマウスボタンを放すと、クリックはキャンセルされます。
このように、ボタンの振る舞いをするViewがどんな仕組みで動いているのかは、MyViewの定義を見ればすぐに分かります。ヘッダファイル(MyView.h)を見ると、MyViewはPPx::BaseViewに加えてさらに4つのクラスから継承されていることが読み取れます。それぞれのクラスは個別にイベントハンドラを加えているわけです。
どのクラスがどのハンドラに対応しているかは、いちいちクラスのソースを見なくても、名前から容易に想像が付くと思います。でも、ここでもっと大切なのは、ボタンの挙動を実現するためにそれぞれのイベントハンドラがどのように連携しながら機能しているかを理解することです。
HIView(=Control)に絡むCarbonイベントのハンドラを持つクラスは、PPxViewEvents.hにリストアップされているのですが、この中を見てみますと、いかにもボタンにふさわしそうな名前のControlClickDoerなんてものがあったりします。しかし今回のMyViewの継承元としては、意外にも登場していません。
さて、ここでBaseViewに加えた4つのハンドラがどのように連携しているのかを説明するのも一興ですが、言葉でああだこうだ説明するよりも実際に動いているものを観察した方がずっと分かりやすいと思います。お勧めの方法は、各ハンドラの先頭に、呼び出された時にログを吐き出すメッセージを仕込んでおくことです。
たとえば、
OSStatus
MyView::DoControlHitTest(
PPx::SysCarbonEvent& ioEvent,
ControlRef inControl,
const HIPoint& inHitPoint,
ControlPartCode& outPartCode)
{
#pragma unused (ioEvent, inControl)
::CFShow(CFSTR("DoControlHitTest called."));
OSStatus status = eventNotHandledErr;
HIRect frame;
GetLocalFrame(frame);
if (::CGRectContainsPoint(frame, inHitPoint)) {
outPartCode = kControlButtonPart;
status = noErr;
}
return status;
}
というような感じです。こうすると、マウスのアクションに対して、Viewがどのように(Carbonイベントを通じて)反応しているかが観察できると思います。表示されるメッセージを少し工夫すれば、かなり多くのことがわかるはずです。
開発ツールよもやま話 Xcode3のバージョン管理 高橋 政明
Xcode3ではいろいろな改良が加えられました。バージョン管理(ソースコード管理)もその一つです。
Xcodeユーザーガイドではバージョン管理(Version Control)となっていますが、XcodeのメニューではSCM(ソースコード管理)となっていて混乱すると思いますので、最初に用語をまとめます。
バージョン管理: Xcodeユーザーガイドの表記です。
ソースコード管理: バージョン管理と同じ意味です。
SCM: Xcodeのメニューです。(ソースコード管理の頭文字)
subversion: バージョン管理ツールのひとつです。
(XcodeではCVSとPerforceも利用可能)
リポジトリ: バージョン管理ツールのデータベースファイルです。
さてXcode3のバージョン管理ですが
リポジトリをXcodeに登録できるようになり、ターミナル操作が必要な場面が少なくなった。
ファイル比較ツールがXcodeに内蔵されUTF-8エンコーディングで日本語コメントがあっても正しく比較できるようになった。この二点が最大の改善点です。
これらの変更点をXcodeユーザーガイドでみても『SCMの拡張。読み込みやチェックアウトなど、すべてのSCM操作を「Xcode」で実行できます。』としか載っていません。調べてみると
Xcode Source Management Guide
http://developer.apple.com/documentation/DeveloperTools/Conceptual/XcodeSourceManagement/30_Source_Control/chapter_3_section_2.html
に英文ですが説明がありました。
チェックアウトやインポートもターミナルを使わずにXcodeで可能です。
リポジトリそのものを作る操作だけはできませんが、リポジトリが存在していればそれをXcodeに登録するだけで利用可能です。
◆Xcode3のバージョン管理の利用手順
1)リポジトリを登録
2)チェックアウト
3)チェックアウトしたプロジェクトの「SCMリポジトリ」を設定
となります。
具体的には
1)リポジトリを登録
Xcodeの環境設定で「SCM」の「リポジトリ」タブを選ぶ
リポジトリリストに追加するため「+」ボタンをクリック
名前と「subversion」などの種類を選ぶ
リポジトリのURLを入力する(必要ならポート、ユーザ、パスワードなども
入力する。SSHのパスフレーズはSSHタブで設定する。)
以上で問題なければ緑のアイコンと『認証されました』の文字が表示されま
す。
2)チェックアウト
SCMメニューの「リポジトリ」を選ぶ
リポジトリを選ぶ
チェックアウトするフォルダを選ぶ
ツールバーのチェックアウトアイコンをクリックする
保存先を指定する
3)チェックアウトしたプロジェクトの「SCMリポジトリ」を設定
チェックアウトしたプロジェクトを開きSCMメニューの「このプロジェクト
のSCMを構成...」メニューを選ぶ
(プロジェクトの情報パネルの「一般」タブが開きます)
「SCMリポジトリ」で1で登録したリポジトリを選ぶ
1〜3の手順でチェックアウトが完了しバージョン管理が利用可能になります。
リポジトリウインドウのツールバー「書き出す」はsubversionならexportです。バージョン管理情報を含まないプロジェクト一式が保存できるので、納品などにはこちらを利用します。
同様に「読み込む」がインポート機能(subversionならimport)です。インポートするフォルダを選び、初期コメントをシートに入力するだけの操作です。ただしフォルダ名がそのままになるのであらかじめプロジェクト名のフォルダをリポジトリ内に作成し、読み込むフォルダ名をtrunkとしてから「読み込む」を行うのがコツのようです。この操作は改良の余地がありそうですね、コマンドラインに慣れているならそちらの方が確実と思いました。操作方法が変わる可能性があるためにマニュアル類に載っていないのかも知れません。
◆ファイル比較にXcodeを指定する
Xcodeの環境設定で「SCM」の「オプション」タブを選ぶとXcode3では比較の方法で「Xcode」が選べます。FileMargeを使った比較では問題のあったUTF-8エンコーディングのファイルでも問題なく比較できます。もちろん比較するソースリスト内に日本語のコメントがあっても大丈夫です。
Xcodeのファイル比較は便利なのですが、バージョン管理を使わずに比較機能だけ単独で使う方法は見つけられませんでした。
Mac OS X v10.5ではsubversionがDarwinに含まれたためインストール作業も必要なくなり、バージョン管理はすぐに(しかも無料で)はじめる事ができます。バージョン管理は個人で開発している場合でも重要で有用なツールです。すべての開発者に導入をおすすめします。
subversionについてはモサ伝251号の書籍紹介でご紹介した「Subversion実践入門 第2版」などを参照してください。
◆本日のまとめ
Xcode3のバージョン管理は強化された。
リポジトリを登録できチェックアウトもターミナルをつかわずに可能
比較ツールがXcodeに内蔵され対応可能なエンコーディングが増えた
ニュース解説 MOSAic
★★★ 開発関連のニュースはwebに掲載中 ★★★
http://www.mosa.gr.jp/?page_id=1017
◇MOSAからのお知らせと編集後記は割愛します◇