2005-02-08
目次
SqueakではじめるSmalltalk入門 第29回 鷲見 正人
本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。前回に引き続き、ブロックの効用と絡めながら一般的な制御構造がどのようにメッセージ送信式で表現されるのかを見てゆきましょう。
▼永久ループ
ブロックに対してrepeatを送信すると永久ループになります。停止するには、cmd-ピリオドでユーザー割り込みをかける必要があります。
| pen |
pen _ Pen new.
pen defaultNib: 1.
pen color: Color red.
pen place: Display center.
[pen turn: 360 atRandom; go: 2] repeat
▼回数を指定した繰り返し
有限回数の単純繰り返しは、繰り返したい数を表わす自然数に対して、timesRepeat: [...]というメッセージを送信します。繰り返したい手続きは、ブロックでパラメータ(引数)として与えます。
| pen |
pen _ Pen new.
pen defaultNib: 1; color: Color blue; place: Display center.
10000 timesRepeat: [pen turn: 360 atRandom; go: 2].
Display restore
▼インデックス付き繰り返し
いわゆるfor-nextループのようなものを意識したメッセージ式としては、#to:do:というメソッドが使用できます。レシーバは始点、第一パラメータは終点の整数で、第二パラメータとして繰り返す処理のブロックを与えます。繰り返し処理のブロックは、ひとつのブロック変数が必要で、これを介して繰り返し時のインデックスが参照可能です。
World findATranscript: nil.
1 to: 10 do: [:idx | Transcript cr; show: idx printString]
降順にするときは、#to:by:do:を使います。
World findATranscript: nil.
10 to: 1 by: -1 do: [:idx | Transcript cr; show: idx printString]
ただ、#to:do:や#to:by:do:は、本当にfor-nextの焼き直し的な意味しかないメソッドなので、メッセージ送信の体裁は整えられていても、けっしてSmalltalkらしい表現とは言えません。通常はCollection >> #do:を使います。
World findATranscript: nil.
(1 to: 10) do: [:each | Transcript cr; show: each printString]
字面では括弧で括っただけなのですが、メッセージ式としては意味がずいぶんと違ってきます。#to:do:の場合との違い(レシーバやメッセージの意味)を改めてじっくり考えてみるのもおもしろいと思います。(1 to: 10)というのは、インターバル(an Interval)と呼ばれる範囲の定まった等差数列オブジェクトを生成する式です。この#do:に象徴される文字列や配列の仲間をレシーバとした、きわめてSmalltalkらしい繰り返し処理の方法については、この後、引き続きご紹介する予定です。
▼条件付き繰り返し
条件に対して、whileTrue: [...]あるいは、whileFalse: [...]というメッセージを送信することで、実現しています。パラメータに繰り返したい処理をブロックで与えるほかに、終了もしくは継続条件であるレシーバもブロックである点に留意する必要があります。
次のスクリプトでは、キーボードのシフトキーの押し下げを感知して繰り返しを終了します。
| pen |
pen _ Pen new.
pen defaultNib: 1; color: Color yellow; place: Display center.
[Sensor shiftPressed]
whileFalse: [pen turn: 360 atRandom; go: 2].
Display restore
条件をnotを送信することで反転させれば、whileTrue:で同じことが可能です。
| pen |
pen _ Pen new.
pen defaultNib: 1; color: Color yellow; place: Display center.
[Sensor shiftPressed not]
whileTrue: [pen turn: 360 atRandom; go: 2].
Display restore
Sensorは、an EventSensorを束縛するグローバル変数で、入力デバイスの状態を手軽に知りたいときに用います。ただ、Squeakの前身であるSmalltalk-80システム時代から使われているレガシーなサービスなので、簡単なスクリプトで便利に使う程度にとどめておくのがよいようです。キーボードの状態の他にも、マウスボタンの押し下げ状態などを知りたいときにも使えます。
EventSensorのスーパークラスに当たるInputSensorのmodifier key、mouse、cursorなどのプロトコル(メソッドカテゴリ)をブラウズすると、マウスやキーボードのどういった状態を取り出すことができるのかを知ることができます。
▼and/or
制御構造ではありませんが、条件を記述する際に用いる論理積、論理和の表現でもブロックは活用されます。お馴染みの論理演算二項式をシミュレートした二項メッセージ式としては、
true | false ” => true (OR) ”
true & false ” => false (AND) ”
というのがありますが、これとは別にキーワードセレクタとして#or:、#and:が用意されています。
true or: [false] ” => true ”
ture and: [false] ” => false ”
もちろん評価結果は同じになりますが、キーワードセレクタを使ったメッセージでは、二項セレクタの#|や#&の場合と違って、パラメータがブロックでなければなりません。これは、レシーバの内容によって、パラメータの処理が省略できる場合に対処するためのものです。たとえば、#or:の場合、レシーバがfalseならパラメータの評価の結果で結論は左右されますが、レシーバがtrueならばパラメータの評価は不要…というような状況を想定しています。
先のスクリプトで、繰り返しの終了条件として「シフトキーの押し下げと同時に画面のクリックする」というものを表現したい場合には、レシーバである条件のブロック内に次のように記述します。
| pen |
pen _ Pen new.
pen defaultNib: 1; color: Color yellow; place: Display center.
[Sensor shiftPressed and: [Sensor redButtonPressed]] " ← ココ "
whileFalse: [pen turn: 360 atRandom; go: 2].
Display restore
バックナンバー:
http://squab.no-ip.com:8080/mosaren/
藤本裕之のプログラミング夜話 #62
さて、予告通りNSApplicationというクラスの使い方に話を進めて行こう。
普通、あるクラスの使い方を説明する場合、まずはコンストラクションから始まって、メソッドのあれこれを説明し、とやるわけだが、このNSApplicationを使うに先立って、我々はこれをインスタンシエイトする必要がない。前回みた、NSApplicationMain()という関数の「やること」の1を思い出して欲しい。そうなのだ、NSApplicationというのはmain()から呼ばれるこの関数によって必ずインスタンシエイトされちゃうのである。そしてそのインスタンスは、プログラム中のどっからでもNSAppというグローバルとして参照できる(この変数はNSApplication.hのなかに宣言されている)。
NSApplicationのメソッドのうち、最も解りやすいのがアプリケーションに付随する各種オブジェクトにアクセスするためのものだろう。例えばウィンドウメニューのようにメニューのアイテムを動的に変更したい場合、アプリケーションのメインメニューにはどうアクセスすればいいか。
NSMenu* aMenu = [NSApp mainMenu];
とやればよい。その他に自分自身のアイコンイメージも獲得できる。……これはどんなときに使うのかな?
NSImage* anImage = [NSApp applicationIconImage];
マルチ・ドキュメントのアプリケーションであれば必ず使うのがorderedDocumentsだろう。
NSArray* documents = [NSApp orderedDocuments];
とやれば、documents に最前面から順番にアプリケーションが開いているドキュメントのオブジェクトを並べてくれる。同じことはウィンドウに対しても可能だ(orderedWindowを使う……昨年のMOSA湘南ミーティングで私が見せたデモはこれを使ってたね)。keyWindow、mainWindowを使えば現在のキーウィンドウ(キーボードからのイベントを受けるウィンドウ)やメインウィンドウ(最前面のウィンドウ)へのポインタを獲得できる。そしてなかでも大事なのが currentEvent だろう。
NSEvent* anEvent = [NSApp currentEvent];
これで、アプリケーションが現在処理中のイベントの中身を知ることができる。例えばあるViewに割り当てたコンテキストメニューを選択されたときなどに、マウスボタンが押されたのがそのViewのなかのどこなのか、正確なポジションが必要な時がある。そういうときはこれを使って処理中のイベントを獲得し、そこからマウスポインタの位置を調べる。この他にもいろいろとあるので自分でドキュメントを参照のこと。とにかくグローバルのNSAppにメッセージ送れば試せるんだから使ってみればいいのである。
さて、これら「参照系メソッド」(今突然ワタシが名付けましたが)のなかに、現在NSAppのDelegateに指定されているオブジェクトを参照するお馴染みdelegateというメソッドがある(これがあるからには当然setDelegate: もあるんだけどね)。で、NSApplicationの機能の真骨頂はどっちかというとこのDelegateを使った方なのである。……というところで本日の予定終了、続きは次回。
(2005_02_02)
高橋真人の「プログラミング指南」第61回
UNIXとしてのMac OS X
〜Perlについて(7)〜
こんにちは、高橋真人です。
さて、前回お話ししたコード例、
for (ord ' ' .. ord '~') {
print chr;
}
ですが、Perlではまた違った書き方をすることが可能です。以前にもお話ししたように、Perlは作者であるLarry Wall氏自らが「『やり方はいくらでもある』がPerlのスローガンだ」と言っているように、上記のような単純なループ文を全く別の書き方で実現することもできるのです。
最近、PythonやRubyなど、Perlに対するアンチテーゼとして「オブジェクト指向スクリプト言語」がいくつか出ていますが、時々これらの言語をPerlと対比して「こっちの方がいい」という文章を見かけます。
私は「道具は用途によって使い分ける」がポリシーであるため、あえて自分を「○○派」という立場に置かないことにしていますが、もともと自称言語フェチ(笑)なのでPythonにもRubyにも興味はあります。ただ、最近はMac OS本体の勉強だけで手一杯でこれらの言語の勉強にはなかなか時間が割けないため、結果、最も使用経験の長いPerlにいちばん親しんでいるということになります。
で、PythonやRubyをPerlとの比較で「Perlのオブジェクト指向は後付けじゃないか」というのは、私も全くの同意見です。以前にこの連載でも「Perlにはオブジェクト指向の仕組みはない」と言い切っていますが、もちろん現行Perlがオブジェクト指向の仕組みを備えていることは知っています。ただ、「何が悲しくてPerlでオブジェクト指向をしなければならないの?」というのが私の感じ方でして、Perlのオブジェクト指向を勉強する暇があったら、その分PythonやRubyの勉強に時間を割きたい、ということです。
ところで、こと「構文比較」という観点から見ると、例えばRubyとPerlを比較して「Perlではこんな書き方しかできないけれども、Rubyならこんなに簡単に書ける」なぁ〜んていう解説を見ることがあります。特にその比較が余りに「表面的」である場合には、私は「ああ、この筆者はRubyに対する愛情の余り、Perlのことを憎んでいるのだな」などと感じて悲しくなります。何故なら、Perlにだってもっと簡単に書く方法はあるのですから!
まあ、そんな話はどうでもいいのですが、例えば先のコード例の場合こんな書き方をすることもできます。
print map { chr } (ord ' ' .. ord '~');
ところで、Perlは時として、かつてのHyperTalkのように「自然な表現でコードを書ける」と思わせる(ただの私の錯覚です)ことがあります。
例えば、
if (/^$/) {
print "Empty line¥n";
}
なんてコードがあったとします。まだ正規表現の説明をしていないのでごく簡単に解説しますが、このコードは現在$_という変数の中身が空文字列、もしくは改行文字のみの場合にメッセージを表示するというものです。しかし、このような書き方は時として冗長に見えることがあります。そんな時に、
print "Empty line¥n" if (/^$/);
なんて、1行でさらっと書いてしまうことができるのです。どうです? スマートだと思いませんか?
このように、Perlでは条件部分を修飾的に記述することができるのです。こんな感じでいちばん肝心の処理の部分を先頭に出すことでコード表現がストレートにできる、というのが今回説明しているやり方です。
それで先ほどのコードですが、ここでも先頭に出ているのはprint演算子で、そのあとにmapやらカッコがゴタゴタと並んでいますね。こういう記述の場合は後ろから読んでいくと分かりやすいのです。処理が後ろから前に順に渡されていくと思ってください。
最初に、丸カッコで囲まれた部分は前回のコードと同じなのでお分かりですね。範囲演算子を使って0×20から0x7Eまでの値のリストを生成しています。
次に、このリストはmapという演算子に渡されます。mapという演算子は、リストを引数に取り、リストの各要素に対して{}内の式を適用します。そしてその結果を再びリストとして返します。今回のケースでは、0×20から0x7Eのそれぞれに chr が適用され(暗黙のうちに$_が使われています)、それぞれ ” “から “~” の文字列のリストになって返されるわけですね。
で、最後にprint演算子がリストを受けて各要素を出力するという具合です。
さて、今回紹介したような「中・上級者向け」(?)の書き方は、巷にあふれるPerlの入門書ではまず見られないでしょう。Perlを基本から、順序だてて解説する場合には、このような「知らなくてもよい」書き方はとかく「特殊視」され、触れられないことが多いのです。
しかし、体系的に順序だてて説明していくだけの時間もスペースもないモサ伝の連載だからこそ、このような「おいしい」部分の紹介にも意味があるのではないかということで、あえてこのような書き方の説明をいたしました。
ニュース・解説
今週の解説担当:小池邦人
【開発環境】
サンフランシスコ Expoの基調講演で取り残されていた新型PowerBook G4がついに発表されました。噂通りにG5やDual Core G4の搭載は見送られており、CPUに関しては若干のクロックアップのみにとどまっていますが、スペックを詳しくチェックしてみると大変魅力的な製品に仕上がっています。さっそくADCの割引制度による購入を検討しようと思い立ち、ADCサイトから入手した購入可能製品リストを眺めてみると、何故だかJISキーボードのPowerBook G4しか載っていません(涙)。以前は、英語版キーボードの機種もちゃんと存在していたはずなのに…?
これはどうしたことかと電話で確認したところ、手続き上リストに載せるのにはもう少し時間がかかるそうですが、今まで通り販売するという方針には変更はないそうです。まずはひと安心ですが、同じことを考えているデベロッパーの皆さんはもう少し待つ必要があるようです。ちなみに、この制度では英語版キーボードのiBook G4の方は販売されていません。多くのデベロッパーは英語版キーボードのマシンが欲しいわけですから、ついでにこちらも購入可能にしてもらえないでしょうか? >アップル社
【テクニカルドキュメント】
前回から2月4日の期間中、Apple社のDocumentationサイトには新規ドキュメントがひとつだけ登録されました。新型Xserve G5 のハードウェア仕様書です。G5を空冷で冷却しようとすると2.3MHzまでが限界なのでしょうか? だから2.5GHz版のXserve G5は登場しないのでしょうか…。また、デベロッパー向けに2つの読み物が登録されています。「.Mac SDK」の本体については、ADCのメンバーサイトからダウンロードすることが可能です。詳しい内容については、前号の木下さんの解説も参考にしてください。それにしても、これ…Carbon APIからは使えるようにはならないのでしょうかね?
「Xserve G5 Developer Note」(PDFあり)
http://developer.apple.com/documentation/index-rev-date.html
「Turning Up the Volume with Audio Units」(読み物)
http://developer.apple.com/audio/audiounits.html
「Using the .Mac SDK」(読み物)
http://developer.apple.com/internet/dotmackit.html
前回から2月4日の期間中、新規のテクニカルノートはひとつも登録されませんでしたが、新規テクニカルQ&Aの方は2つ登録されました。QA1386については、前号の木下さんの解説を参考にしてください。
QA1407「Printer Queue vs. Printer Name」
QA1386「Core Audio & Xcode – Ensuring the latest Core Audio Headers are installed」
http://developer.apple.com/technicalqas/index-rev-date.html
【サンプルソースコード】
前回から2月4日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが2つ登録されました。「AppleScriptRunner」は、AppleScriptを実行するアプリケーションの例題で、以前に登録されていたサンプルの改訂バージョンとなっています。「Audio Unit Effect Templates」の方は、デベロッパー向け読み物の「Turning Up the Volume with Audio Units」の内容と連動しているかもしれません。興味のある方は調べてみてください。
「Audio Unit Effect Templates」(Core Audio関連)
「AppleScriptRunner」(AppleScript関連)
http://developer.apple.com/samplecode/index-rev-date.html
【デベロップメント SDK】
前回から2月4日の期間中、Apple社のSDKサイトには新しいSDKがひとつも登録されませんでした。
http://developer.apple.com/sdk/
MOSAからのお知らせと編集後記は割愛します