2008-04-01
目次
りんご味Ruby 第22回 藤本 尚邦
ウェブや電子メールで英文などの外国語を読むとき、あるいは英作文しなくちゃならないときなど、英語が苦手な私はYahoo!翻訳などのウェブサイトをよく利用します。あらかじめ用意されているウェブのインターフェースをそのまま使うのもいいのですが、もっと手早く手軽に使えるようにしたいということがありますよね。ネットで探してみれば何かそのためのお助けツールが見つかるかもしれませんが、自分が使いやすいように作ることもできます。私の場合は、RubyでYahoo!翻訳のテキスト翻訳を使うためのライブラリを作って、これを元にシェルコマンド・Emacsコマンド・Quicksilverプラグインを作って使っています。今回から数回、このライブラリをどんな風に作るか・使うかを紹介していきます。
■ テキスト翻訳ライブラリの使い方(仕様)
テキスト翻訳の機能は、「何語から何語に翻訳したいのか?」および「翻訳対象テキスト」を入力に「翻訳結果テキスト」を出力する関数として見立てることができます。
Yahoo!翻訳によるテキスト翻訳器をYahooHonyakuという名前のクラスとして定義することにして、翻訳を実行する上記の関数をテキスト翻訳器のただ一つの公開されたインスタンスメソッドとして実装することにします。テキスト翻訳器(YahooHonyakuのインスタンス)を生成(new)し、メソッドを呼び出して翻訳を実行するといった使い方が基本になります:
translator = YahooHonyaku.new
translator.translate(:je, "おはよう") => "Good morning"
translator.translate(:ej, "Good morning") => "おはよう"
1つめの引数が「何語から何語に翻訳したいのか?」で、2つめの引数が「翻訳対象テキスト」を表します。「何語から何語に翻訳したいのか?」は、それぞれ対象言語、結果言語を表す2文字のシンボル(または文字列)で表します。:ej なら「英語から日本語に訳」、:jeならその逆といったようになります。
実際にコードを書いたりデバッグなどで試してみるときには、翻訳器を生成して翻訳するところまでを一度にやってしまいたいことも多くなりそうです。それは翻訳器クラスのクラスメソッドとして用意しておくことにしましょう:
YahooHonyaku.translate(:je, "おはよう") => "Good morning"
YahooHonyaku.translate(:ej, "Good morning") => "おはよう"
■ 翻訳器クラスの概要
Yahoo!翻訳による翻訳器クラスの定義の概略は以下のようになります。
------------------------------------------------ yahoo-honyaku.rb
class YahooHonyaku
def self.translate(mode, text)
new.translate(mode, text)
end
def translate(mode, text)
post!(:eid=>_eid_(mode), :text=>text)
@yt_result
end
private
def _eid_(mode)
raise NotImplementedError
# 変換モードをYahoo!翻訳の実引数の値に正規化する
end
def post!(form_args={})
raise NotImplementedError
# Yahoo!翻訳に実引数を渡して呼び出し
# 結果をパースして
# 翻訳結果を @yt_result にセットする
end
end
------------------------------------------------
翻訳を実行するインスタンスメソッド translate から呼ばれる post!では、HTTPのPOSTメソッドを介して、テキスト翻訳を実行して、HTMLとして返された結果をパースして、翻訳されたテキストを取り出します。この中身は次回以降で実装します。
■ クラスメソッドと特異メソッド
Rubyでは、1つ1つのオブジェクトに個別にメソッドを定義することができます。そのようなメソッドを特異メソッドといい、以下のように定義します:
def オブジェクト.hoge(...)
...
end
あまり意味のない例ですが:
obj = Object.new
obj.hoge # NoMethodError発生
def obj.hoge
puts "hoge hoge"
end
obj.hoge # hoge hoge と印字
Object.new.hoge # NoMethodError発生
この hogeというメソッドは、objと名付けられたオブジェクトだけに実装されます。YahooHonyakuに戻ると、翻訳器の生成と翻訳を一度にまとめて実行するクラスメソッドは:
def self.translate(mode, text)
new.translate(mode, text)
end
のところで定義しています。このselfはYahooHonyakuクラス自体を表しています。つまりこのメソッド定義は、self(すなわちYahooHonyakuクラス自体)の特異メソッドを定義していることになります。Rubyでは、クラス自体も数値や文字列などと同等に扱える値(ファーストクラスオブジェクト)です。Rubyでは、クラス自体に定義された特異メソッドのことを、便宜上クラスメソッドと呼んでいるだけなのです。
藤本裕之のプログラミング夜話 #135
前回最後で私はちょっとおかしなことを書いた……いや書いたつもりだったんだけど、誰からもありゃどういう意味だと聞かれたりしなかったのは、私が思ってることが実は常識なのかそれとも誰もこんな文章読んでないのか。念のために再録しておく。こう書いたのね……。『俺たちが作っているこいつは実のところ「ソフトウエアの名に値しない何か」なんぢゃないかと思っている』。ほんぢゃなんだってんだ? と誰が突っ込んでくれると思ったんだけどね(笑)。
WebのYahoo辞書の「大辞泉」で「ソフトウエア」というのを検索してみると以下のような結果が表示される。
1. 機器類を用いて行う物事の、情報・理論など無形の部分
2. コンピュータの、処理の手順を示すプログラムの総称
そしてこの両方に、反対語として「ハードウエア」と書いてあるのね。これに対して、e-Wordsが提供しているIT用語辞典だと当然のように「ソフトウエア」の意味は上の2の方だけになる。曰く……
狭義にはコンピュータプログラムとほぼ同じ意味(中略)。広義にはコンピュータが扱うプログラム以外のデータを含めてソフトウェアと呼ぶ場合もある。
確かに我々が作っているのは「コンピュータプログラム」なんだけどさ。
「大辞泉」がまず挙げているように、その昔「コンピュータ」がMTをカタカタ回しつつ怪獣の弱点を紙テープで教えてくれるものであり、「プログラム」と言えばそれは「式次第」や「演目表」のことであり、「IT」と言ったらスティーブン・キングの恐怖小説(これは知ってるひとだけか)しか思い浮かばなかった……新石器時代中葉ごろ(嘘)、「ソフトウエア」というのは、「テレビ受像機やビデオデッキに対して映し出される映像(あえて「映像作品」とは言わないが)」のことであり、楽器やレコードに対して演奏される楽曲」のことであり、書籍や雑誌といった媒体に対してそこに印刷される「文章」のこ
とであった、のである。
今は知らず、他人は知らねど、少なくとも私自身とその周囲には、我々が作るコピュータプログラムもそうした広義での「ソフトウエア」の範疇に入るものであり、すなわちこれは「新しく生まれた『ソフトウエア』のありかた」であるという考え方があった。いやホントですって。
そういう考え方がわりと一般的になりつつあった証拠に、私の手元には10年ほど前に作ったソフトウエアに関する契約書がある。その第1項は甲(このソフトの販売会社)が乙(ワタシのこと)にこのCD-ROMの「企画印税を支払う」というもので、1枚あたりの企画印税は税抜き価格より容器代を控除した金額の1%、容器代は税込み価格の10%となっている。第2項にリクープ(recoup)の取り決めがあって、「本件企画印税は上記CD-ROMの工場出荷枚数7,001枚より発生するものとする」……つまり7,000枚までの売り上げに関する印税報酬は、このソフトの製作費として貰ったお金と相殺で、7,000枚を超えるヒットとなったら1枚につき……計算すると18円くらいになったのかな? が支払わ
れるというわけである。え? 1%は安すぎないかって? このソフトは私が基本のコードを書き、それをウインドウズ版に移植した人がいて(ハイブリッドだった)、その他にもデータを作った人、音楽を載せた人などもろもろが印税を分け合うので1%なのである。別に不当な契約ではない。
それに結論からいうと、このソフト、それなりに話題にはなったものの7,000枚を超えては売れず、私には製作費以外一銭も入ってこなかったので、この1%が別に0.1%でも逆に2%でもその後の世界は何も変わらなかったのである。が、しかしここで言いたいのはそういう愚痴ではなくて(笑)、コンピュータソフトウエアがあんな風に他の「ソフトウエア」と同様なものとして扱われるのは果たして適当だったのか、ということなんである。当時は「いいこと」と思っていたんだけどね。
(以下次回 2008_03_29)
高橋真人の「プログラミング指南」第133回
〜XcodeによるPowerPlant X入門(22)〜
こんにちは、高橋真人です。
さて、BaseViewを拡張してボタンの仕掛けを組み込む要領が分かったところで、これからはいよいよPPxならではのメリットを生かした拡張をしていきます。
Carbonフレームワークの一部であるHIToolboxの提供するHIViewには、サブクラスを作る仕組みが備わっています。しかし、HIToolboxはCベースのAPIであるため、サブクラスを作れると言っても、オブジェクト指向言語でやるほどスムーズではありません。
慣れてしまえばそんなに難しくもないのかもしれませんが、それなりにコードを書く必要もあり、少し煩雑な印象があります。それに対して、PPxの場合にはC++というオブジェクト指向に対応した言語を使うため、ずっとスムーズに書くことができます。
もっとも、PPxでも内部的にはHIViewのCのAPIを使って実装を行っているわけですから、やれることにはそんなに違いはありません。でも、サブクラスされたViewが完全に独立したオブジェクトとして振る舞うので、コードのすっきり感はずっと上がるのではないかと個人的には思っています。
サブクラスを作れることの大きなメリットは、“既存の仕組みを流用”し、足りないところは補い、変更したい部分は書き替える(オーバーライド)ことができることです。ですから、HIViewでサブクラスを作れるという意味は、もともとシステムが備えている様々な種類のView、つまり、ボタンとかMLTE(簡易エディタ機能を持ったテキストエリア)などの仕組みをそのまま流用しつつ、さらに自分なりに新たな仕組みを加えられるということです。
しかし、私が以前探してみた範囲では、Appleの提供しているサンプルはすべてがHIView(最もベーシックなView。それだけでは何も機能は持たないので、もともとサブクラス化して使うようになっているもの)からの継承した例でした。
でも、もし本当にHIViewからだけしかサブクラスを作れないのだとすれば、HIViewの掲げる「サブクラスを作れる」という看板には偽りあり、ですよね。
そんなわけで、本当にダメなのかをちょっと試してみました。
結果は全く問題なしでした。たくさんテストしたわけではありませんが、シンプルなボタンのサブクラスを作ることも難なくできました。
そんなわけで、これからはこれを実際にやっていきます。もちろんPPxでです。ただ、PPxの拡張の柔軟性をお伝えしたいので、多少のバリエーションを付けながら、複数のアプローチでやってみたいと思っています。とは言え字数の都合上、余り凝ったことはできませんので、やること自体はシンプルですが。もっとも、その方が理解するためには好都合かもしれませんね。
さて、最初にやるのはごく普通のボタンに装飾を加えることです。PPxにはPushButtonというシステム標準のボタン(HIViewではkHIPushButtonClassIDと表します)のためのクラスがありますが、これのサブクラスを作って装飾(というほど立派なものではありませんが・笑)を施してみます。
では、早速やってみましょう。
例によって一つ前のプロジェクトを複製して、PPxForXcode07を用意してください。(もう、細かい説明は必要ありませんよね?)
今回は、コードを一挙に掲載するのではなく、段階的に変更を加えていきます。
まずは準備段階として、前回作ったView(MyView)の大きさをボタンの大きさに合わせます。そのために以下の変更を加えます。
【変更の対象:MyApplication.cpのDoSpecificCommand()】
《変更前》
HIRect frame = CGRectOffset(contentFrame,
20.0, contentFrame.size.height - 60.0);
frame.size = CGSizeMake(120.0, 40.0);
《変更後》
HIRect frame = CGRectMake(
contentFrame.origin.x + 20.0,
contentFrame.origin.y + contentFrame.size.height - 60.0,
120.0,
20.0);
前回は、ちょっと変な書き方をしたのですが、今回は素直にしました。これで、“普通の”ボタンのサイズでViewを作るようになります。
あと、もう一つ。今度はMyViewの方の準備のための変更です。
【変更の対象:MyView.cpのDoControlDraw()】
《変更前》
float alpha = 0.4;
if (::IsControlHilited(inControl) and ::IsControlActive(inControl)) {
alpha = 0.8;
}
::CGContextSetRGBFillColor(inContext, 0.3, 0.6, 1.0, alpha);
::CGContextFillRect(inContext, frame);
《変更後》
::CGContextStrokeRect(inContext, frame);
では、ここで一度ビルドして走らせてみましょう。
表示されるのは、とりあえず黒い線で書かれた枠だけですが、クリックしてみるとちゃんとボタンとして機能していることが分かります。今はビジュアル的には反応はしませんが。
次回はさらに変更を加えていきます。
開発ツールよもやま話 MallocDebug 前編 高橋 政明
MallocDebugはパフォーマンスツールのひとつでメモリ関連の分析ツールです。Xcode Toolsをインストールすると/Developer/Applications/Performance Tools/フォルダにインストールされます。最新バージョンは1.7です。
Cocoa Fundamentals GuideのMallocDebugの説明を引用すると
プログラムに現在割り当てられているすべてのメモリブロックを割り当て時の呼び出しスタック別に整理して表示します。一目見ただけで、アプリケーションがどの程度の割り当てメモリを消費しているか、そのメモリがどこから割り当てられているか、どの関数に大量のメモリが割り当てられているか分かります。MallocDebugでは、プログラムのほかのどこでも参照されていない割り当てメモリを見つけることができるため、リークを見つけたり、メモリが割り当てられた場所を正確に追跡したりするのに役立ちます。
【Cocoaとは? 開発環境 その他の開発ツールより引用】
水漏れ(リーク)と虫眼鏡のアイコンからも直感的に分かるように、最も活躍するのはメモリリークを見つける時でしょう。
MallocDebugは分析対象のアプリケーションと同時に走らせてダイナミックにメモリの確保や解放処理をどこから呼ばれたかと同時に記録するツールです。それを分析しメモリリークなどを表示してくれます。Helpメニューからリリースノートを見るとMac OS XのPublic Betaの時にバージョン1.0だったことがわかります。MallocDebugの使い方をマスターすればどのバージョンのMacOS Xでも使えるわけです。
MallocDebugでアプリケーションを分析するために何らかの特別なライブラリをリンクしたり、特別な関数を呼び出したりする必要はありません。
◆概要
画面や操作を文字だけで説明するのはかなり辛いのでAppleのサイトを引用しながら説明します。Memory Usage Performance Guidelines の Examining
Memory Allocation PatternsにMallocDebugの説明が載っています。
http://developer.apple.com/documentation/Performance/Conceptual/ManagingMemory/Articles/FindingPatterns.html
このページのFigure 1にMallocDebugの画面の説明があります。
一番上がLaunch informationで分析対象のアプリケーションを指定し必要なら起動時の引数を設定します。(Finderからダブルクリックで起動するアプリの場合引数の指定は不要)
その下はMallocDebugの操作用ポップアップボタンと「Mark」「Update」ボタンがあります。
その下のCall Stack Browserはメモリ確保を行った関数の呼び出し階層と確保した容量などを表示する部分です。
一番下のMemory Buffer Listが確保されているメモリのアドレスやサイズなどの一覧です。ここをダブルクリックすると対応するメモリの内容を16進数表示で確認する事ができます。
確保したメモリはMallocDebugにより0×55で埋められ(初期化)ています。また確保したブロックは0xdeadbeef と 0xbeefdead (この部分文字ではなく16進です)で挟まれています。このことを念頭に16進数表示のMemory ViewerPanelの内容を見る事で自分のプログラムのどの部分が処理したかや、意図通り動作しているかを追求することができます。
◆基本操作
まず分析するアプリケーションを指定します。Browseボタンで選ぶこともできますし、Finderからコンボボックスへアプリケーションアイコンをドラッグ&ドロップも可能です。過去に分析したアプリケーションのフルパスをコンボボックスから選ぶこともできます。
Launchボタンで指定したアプリケーションを起動します。
Call Stack Browserにはmallocを呼び出した関数が階層表示されます。フレームワークや様々なAPIが確保するメモリもすべて記録表示します。
表示モードはDisplay Modeポップアップボタンで変更できます。デフォルトのStandard modeはmainから関数の呼び出し階層を表示します。(Figure 3参
照)
Inverted modeはStandard modeの逆に表示します。
Flat modeはメソッドまたは関数ごとに確保したメモリ順にソートして表示します。
Analysis Modeについてですが、All Allocationsは現時点のすべてのメモリを表示します。
Allocations since MarkはMarkボタンを押した後の操作などで観測対象のアプリケーションが新たに確保したメモリだけを表示します。注目部分だけを観測できます。
Leaksはメモリリークを表示します。詳しくは次回説明する予定です。
Overruns/underrunsはバッファの直前または直後への不正な書込みを表示します。直後へオーバーした場合は「>」マーク、直前へ書き込んだ場合は「<」マークをMemory Buffer Listに表示します。
(後半へ続く)
◇MOSAからのお知らせと編集後記は割愛します◇