本連載では、名前はよく耳にしていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。例として提示した簡単なペイントスクリプトの解説をしていますが、今回は、ループや条件分岐の部分を取り上げます。前回の解説では、4行目まででは「pen」という一時変数を用意し、Penのインスタンスをそれに束縛し、描く線の太さと色をいずれも、主にメッセージ送信により実現していることを示しました。どんなオブジェクトに、どのようなメッセージを送って、何をさせるのか...。“メッセージ指向”と呼ぶべきSmalltalkオリジナルの「オブジェクト指向」に身をゆだねるとき、ユーザーは常にこれらのことに意識を向けなければなりません。position]]“メッセージ指向”においては、通常のプログラミング言語では専用の構文を用意するループや条件分岐でも「オブジェクトに対するメッセージ送信」のスタイルで表現することをあくまで貫きます。[...]」というメッセージ送信が“条件分岐”を表わす例になっています。]で括られる記述は、ブロック(BlockContext)と呼ばれる“処理”をオブジェクト化したもののリテラル式です。]を使っていることからすぐに分かるように、Objective-Cはこの種のオブジェクトやそのリテラル記述はサポートしていません(リテラル記述を代えて同種のオブジェクトを提供する外部ライブラリ自体は存在します)。他方で、LISPなどに精通しておられるかたなら、無名関数(λ式)と同種のものだと言えばピンとくるはずです。ブロックについては追って詳しく解説を加えなければならないときが来ると思いますが、ここでは簡単に。]で括られた一連の式はその場では評価されず、処理そのものとしてオブジェクト化され、変数に束縛したり、パラメータとして受け渡すなど第1級のデータとして扱うことが可能になります。4」という処理を表わすオブジェクトとして扱うことが可能になります。変数への束縛も可能です。メッセージ「value」を送信することで、中に含まれる処理の遅延評価を行なうことができ、結果の「7」を得ることができます。”ブロックがオブジェクトであり、メッセージの受信者(レシーバ)になることができる具体例は、件のプログラムの5行目にも見つけることができます。shiftPressed]というブロックオブジェクトに送信されています。#whileFalse:は、レシーバのブロック内の評価値がfalseの間、パラメータのブロックの評価を繰り返すメソッドです。レシーバの評価値がtrueを返す間だけ繰り返す#whileTrue:というメソッドもあります。ちなみに、論理反転のためのメッセージ「not」を使うことで、5行目は、次のように書き換えても同じ意味になります。[Sensorにメッセージを送ることで、我々はその刹那のキーボードやマウスの状態を知ることができます(註)。メッセージ「shiftPressed」の送信では、シフトキーが押されているかどうかを真偽値(true、false)の返値として得ることが可能です。このことから分かるように、#whileFalse:、#whileTrue:を起動するメッセージのレシーバは、ブロックでも、特に真偽値を返すブロックであることが期待されます。[]のような場合、レシーバは評価時に常にtrueを返すので、結果、無限ループになります。無限ループから脱するには、cmd-.(ピリオド)をタイプしてください。Sensorはクラスではなく、InputSensorあるいはEventSensorに属するインスタンス(システムを構成するオブジェクトのひとつ)を束縛するグローバル変数です。グローバル変数はいったん定義してしまえば、あとは宣言なしでいつでもどこででも使用できる変数で、大文字から始めるきまりになっています。実は、クラスもこのグローバル変数に束縛されているオブジェクトに過ぎません。8行目から10行目までがメッセージ送信によって表現された条件分岐の例です。redButtonPressedは、評価の瞬間、マウスボタン(2ボタン以上のマウスなら左ボタン)が押されているかを真偽値で返す式です。偽時処理」というメッセージを送ることで、通常のプログラミング言語における条件分岐をシミュレートしています。レシーバがtrueなら第1パラメータである真時処理ブロックを、falseなら第2パラメータである偽時処理ブロックを評価します。これで、マウスボタンが押されていれば、ペンを下げて移動し(描画)、押されていないときはペンを上げた状態で移動(マウスポインタへの単なる追従)という処理を表わしています。この#ifTrue:ifFalseの実装方法はおもしろいので、引き続いて次回、もう少し詳しく解説を加えたいと思います。註:ただしSensorは、Squeakの前身であるSmalltalk-80時代から引き継がれた、MVCと呼ばれる古いGUIフレームワーク(Cocoaでも、この亜種が採用されていますね)で使われていたグローバル変数で、バックワードコンパチビリティの目的で使用できているに過ぎません。現在のMorphicと呼ばれる新しいGUIフレームワークでは、より高機能なActiveHandを使うことが推奨されます。ここではコードを簡素化するため、あえてSensorを用いました。Handlerを活用する前回、サンプルアプリケーションに実装したイベントハンドラルーチンを解説しました。その中で、ユーザがメニュー選択を行った場合には、メニュー項目に一対一で対応したコマンドID(Nibファイルに定義されている)がハンドラへ送られて来ると説明しました。再度、それを処理している部分をピックアップしてみます。break;この部分には、ユーザがアプリケーションメニューの「MOSAについて...」「MOSAを終了」、もしくはファイルメニューの「新規」と「開く...」を選択した時の処理が記述されています。ここで注目すべき点は、各ケースの出口でretにnoErr(ゼロ)が代入されていることです。このretは、イベントハンドラの最後にreturnに代入されてルーチンの「返り値」となっています。Eventは各オブジェクトに実装されたイベントハンドラ間を階層にそって伝搬(継承)していくと説明しました。コントロールに実装されたハンドラからウィンドウのハンドラへ、そしてアプリケーションのハンドラへといった流れがあるわけです。Eventの伝搬はそのハンドラでストップします。Eventはもう次のイベントハンドラへは送るな!」という意味になるわけです。Eventの伝搬を継続(サッカーでのパスのスルーと同じ)させる場合には、noErrの代わりにeventNotHandledErrを返します。eventNotHandledErrはルーチンの最初でretに代入されていますので、処理内で再度何かを代入しなければ、これがディフォルトの返り値となります。Eventに対応した処理は、必ずしもユーザが実装したイベントハンドラで実行されるとは限りません。Eventは最終的にはシステムが用意したイベントハンドラで処理されることになります。Handler」と呼びます。コマンドIDが’abou’のケースでは、openAboutWindow()でアバウトウィンドウを表示しています。Eventの伝搬にストップをかけています。ここで簡単な実験をしてみることにします。以下のようにopenAboutWindow();をコメント行にしたらどうなるでしょうか?当然、メニューを選択しても何も起こりませんね。break;今度は、ret=noErr;をコメント行にしてみます。Handlerへとスルーしたため、システム側でもディフォルトのアバウト表示が成されたわけです。Handlerに実装されました。10.3以降のみなので要注意)。Handlerが用意されており、適切なディフォルト処理を実行してくれます。先ほど紹介した4つのケースで、状況によってはretにnoErrが代入されないケースがひとつだけありあます。それは、アプリケーションメニューの「MOSAを終了」に準じたコマンドIDが’quit’のケースです。ここには「アプリケーションを終了させる」処理が記述されています。その本体が、以下のquitApplication()ルーチンです。retがゼロならアプリ終了、1ならば終了はキャンセル}お馴染みの「保存しますか?」アラートで「キャンセル」ボタンが押されて終了が中止されると、retにnoErrが代入されて処理がそこでストップします。この場合、アプリケーションは終了しません。Handlerへと継承されます。そこでメインイベントループから抜けるためにQuitApplicationEventLoop()が呼ばれ、アプリケーションは完全に終了します。Handlerの力を借りないで)すべて自前で記述すると、以下の様になります。現状の処理と比較してみてください。Handlerへ処理を継承させた方が効果的に目的を達せられる場合がある一例です。このテクニックを習得すると色々と便利に使えます。サッカーにおいて、パスをスルーする前に足でボールに触れ、方向やスピードをちょっと変化させる感じでしょうか?攻撃にバリエーションができます(笑)。Handlerのような便利な仕組みはなく、ありとあらゆるイベント処理を自分自身で記述する必要がありました。Handlerが受け持ってくれていますので、効率的に開発が行えるわけです。次回もイベントハンドラの4つのケースの処理について説明したいと思います。ウィンドウに実装するイベントハンドラの例題として、先に紹介したopenAboutWindow()の周辺を攻めてみたいと思います。前回は、ERChangeNotificationJMS(以下ERCN)がどのようなときに役立つかを説明しましたが、今回はERCHのセットアップ方法を解説します。ERCNを使用する場合、別途OpenJMSのセットアップが必要になりますので、まずはそちらから紹介したいと思います。OpenJMSセットアップまずOpenJMSの入手方法ですが、次のいずれかのURLからダウンロードしてください。今回は原稿執筆時点での最新バージョンのopenjms-0.7.6.1.tar.gzをダウンロードしてください。・最新版ダウンロードhttp://openjms.sourceforge.net/downloads.html・旧バージョン/ソースコードダウンロードhttp://sourceforge.net/project/showfiles.php?group_id=54559次にターミナル上でOpenJMSをダウンロードしたディレクトリに移動し、ダウンロードしたファイルを以下のコマンドで展開します。”openjms-0.7.6.1′′という名前で展開されますが、この名前を”openjms”に変更してください。-展開したファイルを”/usr/local”に移動します。Finderの「移動」メニューから「フォルダへ移動...」を選択し、”/usr/local”と入力してください。すると普段は不可視になっている”/usr/local”がFinder上に表示されますので、ここに展開した”openjms”フォルダをコピーします。OSではFinder上でコピーすることができません。Panther以前のバージョンをお使いの場合はターミナル上でコピーをおこなってください。Pantherでもターミナル上でコピーしてかまいません。・OpenJMSのインストール先のパス/usr/local/openjmsこれでOpenJMSのインストールができましたので、次にOpenJMS起動のための前準備をおこないます。今回OpenJMSの起動はターミナル上でおこないますが、起動前に環境変数の設定が必要になりますので、ターミナル上で以下の2つのコマンドを実行してください。Pantherの場合はbashがデフォルトのシェルになっています。WONDERのソース(Wonder-src-2.0.zip)にOpenJMS用の設定ファイルが含まれていますので、以下のとおりコピーします。・コピー元ファイルCommon/Frameworks/ERChangeNotificationJMS/Support/rmi_jms_jdbm.xml・コピー先ディレクトリ/usr/local/openjms/config/さて、いよいよこれでOpenJMSを起動する準備が整いましたのでターミナル上で次のコマンドを入力し、OpenJMSを起動してください。ここではOpenJMSの起動スクリプト(startup.sh)があるディレクトリに移動し、設定ファイルを指定した状態でOpenJMSを起動しています。&OpenJMSを終了させるには以下のコマンドを入力してください。../config/rmi_jms_jdbm.xmlOpenJMSのインストールやセットアップの詳細については次のURLに解説があります。WONDER(Wonder-2.0.zip)からERCNを以下のとおりコピーします。0.7.6を元にビルドされています。そこでまずERCHを最新版のOpenJMSに対応させます。0.7.6用のjarファイル存在していますので、まずはそれらのファイルを削除します。openjms-client-0.7.6.jarOpenJMSを利用するのに必要なjarファイルですが、以下のURLにOpenJMSを使用するのに必要なjarファイルの一覧があり、ここで説明されているファイルは”/usr/local/openjms/lib/”にインストールされています。commons-logging-1.0.3.jarこの中にはERCNでは実際には使用されないファイルも含まれていますが、とりあえず5つのファイルをすべてERCNの”/Resources/Java/”にコピーします。これでこれでフレームワークの準備は完了です。・コピー先ディレクトリERChangeNotificationJMS.framework/Resources/Java/アプリケーションのERCN対応まずERCN対応をおこなうプロジェクト開き、フレームワークグループにERCNフレームワークを追加します。次にプロジェクトのPropertiesファイル(存在しない場合は新規に作成してください)にERCNの設定を追加します。WONDERのソースにサンプルが付属していますので、まずはこちらをコピーします。サンプルファイルは次のパスにある”SampleProperties.txt”です。・ERCNサンプル設定ファイルCommon/Frameworks/ERChangeNotificationJMS/Documentation/最後にプロジェクトをビルドします。これでERCNに対応したアプリケーションが作成されます。このときERCNに対応するからといってアプリケーションのソースコードはいっさい変更する必要はありません。ERCNフレームワークの追加をおこなえばあとは自動的に処理がおこなわれます。旧バージョンのERCNをすでに使用していた場合や、ERCNに含まれるjarファイルを入替えた場合は、アプリケーションのプロジェクトを再ビルドしてください。ERCNの動作確認ですが、まずアプリケーションのインスタンスを2つ起動して、両方のインスタンスでデータベース上の同一のデータをFetchし、EOを作成します。次に、片方のインスタンスだけでそのEOを変更してください。するともう片方のインスタンス上でも自動的にEOの変更内容が反映されていることが確認できます。これでインスタンス間でのEOの同期が実現できました。Xの開発ツールXcodeのVer.1.5がリリースされた。5がバンドルされるので、事実上機密情報ではなくなる事を考慮し、概要をお知らせしたい。1.5の新しい機能としては、ビルドされたオブジェクトでの呼び出されていないコードの自動削除、リモートでバッグ、Javaでのキーワードなどの自動入力、Subversionのサポート、ネイティブビルドのlexやyaccそしてAppleScriptのサポート、Antのサポート、アプリケーションサーバ向けの開発機能の強化などとなっている。バグ修正やパフォーマンスの改善もされている。コンパイラのgccはVer.3.3となっている。7を出して以来のバージョンアップとなる。開発ツール自体をCarbonベースでかなりの部分を書き直し、エディタやプロジェクト管理機能が従来のバージョンより充実している。XMLベースでのIDEでのスクリプト機能をサポートするなど機能強化している。1.5でリモートデバッグがサポートされた。sshでネットワークした別のコンピュータ上で稼働するプログラムのデバッグが可能なので、たとえば全画面で実行しているプログラムのデバッグもXcodeでできるということになる。sshのキー生成、Xcodeでの基本的な設定方法がまとめられている。Management)についての文書が公開された。CVS、Subversion、Perfoceについての手法が記載されている。いずれも、ソースのインポート自体はコマンドを使って行うが、その後はXcodeでの機能を使えばいいとなっている。nibファイルやバンドルなどについてはCVSではcvswrappersというファイルをインストールする事で、ロックをかけることができることなどが解説されている。CVSではバンドルやファイルパッケージに対して複数のデベロッパが編集をかけないようにする仕組みがあるが、SubvertionやPerfoceでは利用できない。OSは米国アップルコンピュータ社の登録商標です。そのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。このメールの再配信、および掲載された記事の無断転載を禁じます。Artistsアクセスリンクについて個人情報の取り扱いについて支援のお願いお問い合せこのサイトに掲載されている文章、画像を含む一切のデータの無断転載を禁止します。