第3回 メッセージの詳細 (4月23日; 24日)

今日の課題

■ ブロック・オブジェクト

ブロックは、ステートメントの並びを持つオブジェクトである。ステートメントは、レシーバとメッセージの組などである。ブロックに、あるメッセージを送ることで、ステートメントの並びを実行させることができる。

ブロックを定義する書式

(引数の無い場合) [ ステートメント1. ステートメント2. …. ステートメントn ]
(引数の有る場合) [: 引数1 : 引数2 … : 引数m | ステートメント1. ステートメント2. …. ステートメントn ]

ブロック内で、ローカル変数を使用するには、ステートメントの始まる前に、| 変数名1 変数名2 … 変数名k | を記載する。

ワークスペース上で実行するには、[ の始まりから ] の終わりまでを選択して、ALT+d を押す。

なお、選択は、シフトキーを押しながらカーソルキーの「↑」を押す、または、マウスの左ボタンを押しながらマウスカーソルを動かす。

ブロックを実行する書式

(引数の無い場合) b value
(引数の有る場合) b value: 値1 value: 値2 … value: 値m

ブロックの返り値は、最後に実行したステートメントの返り値である。

準備

今日の演習のためのプロジェクトを作り、その中で、Sqeuak の作業をすることにしよう。

例:「ナビゲータ」→「新しく作る」を選択する。「名前無し」のウインドウの灰色部分を右クリックし、黒いアイコンを左クリックして、適当な所へ動かす。「名前無し」をクリックし、名前を変える。プロジェクトへ入る。

練習1

(1) 赤い星を表示する手続きを、ブロックでまとめよう。そのブロックを変数 redStar で指そう。

ワークスペースで以下を行なう。
redStar := [ | s |              (ローカル変数 s を宣言)
      s := StarMorph new.   (星のインスタンスを作る)
      s color: Color red.   (星の色を決める)
      s openInWorld ]       (星を画面に表示する)

タブキーを押して、インデントを入れると、カッコ良くプログラムが書ける。

(2) 赤い星の表示を実行しよう。

ワークスペースで、以下を行う。
redStar value

練習2

指定した座標に赤い星を表示する手続きを、ブロックで作成しよう。座標は、2 つの引数でブロックに与えるものとする。以下の方法で動作するようにしよう。

ワークスペースでの実行の様子
redStar := ブロックの定義(自分で作ろう)
redStar value: 200 value: 300

ここで、星のインスタンスに、座標を指定するには、メッセージ position: を送る。このメッセージの引数は、位置のインスタンスである。

位置のクラスは、Point である。座標を指定しながら位置のインスタンスを作るには、メッセージ x:y: を送る。

答えはココ ⇒

ブロックの返り値が最後に処理した結果ということに注意すると、こんな答えもある⇒

■ メッセージによる選択

真偽を表すオブジェクトがある。true と false である。たとえば、「1 < 2」の返り値は true オブジェクトであり、「1 > 2」の返り値は false オブジェクトである。

真偽のオブジェクトは、次のメッセージを処理することができる。
メッセージ true オブジェクトの処理 false オブジェクトの処理
ifTrue: 引数のブロックを実行する 何もしない
ifFalse: 何もしない 引数のブロックを実行する
ifTrue:ifFalse: 第1引数のブロックを実行する 第2引数のブロックを実行する

結果として、選択(いわゆる if 文)の処理ができる。

練習3

トランスクリプトを出しておき、ワークスペースで以下の動作を確認しよう。
1 < 2   (ALT+p を押す。true/false のどちらが返るかな?)
1 > 2   (ALT+p を押す。true/false のどちらが返るかな?)
true ifTrue: [Transcript show: 'yes' ; cr]  (ALT+d を押す。)
false ifTrue: [Transcript show: 'yes' ; cr] (ALT+d を押す。)
(1 < 2) ifTrue: [Transcript show: 'yes' ; cr]  (ALT+d を押す。)
(1 > 2) ifTrue: [Transcript show: 'yes' ; cr]  (ALT+d を押す。)

※ セミコロンは、レシーバが共通であることを表す。つまり、メッセージ「cr」のレシーバは「Transcript」。

■ メッセージによる反復

ブロックにメッセージを送ることで、反復の処理をすることができる。原理は選択のものと似ている。
メッセージ レシーバのブロック・オブジェクトの処理
whileTrue: レシーバのブロック・オブジェクト(自身)の処理結果が true となれば、引数のブロックを実行し、再度、自身に whileTrue: を処理させる。
whileFalse: 自身の処理結果が false となれば、引数のブロックを実行し、再度、自身に whileFalse: を処理させる。

練習4

トランスクリプトを出しておき、ワークスペースで以下の動作を確認しよう。
i := 1
[ i < 10 ] whileTrue: [ Transcript show: i asString. i := i + 1 ]

■ 小レポート

色を変えながら星を並べて表示するプログラムを作ろう。

(1) まず、座標(sx,sy)から右にdx、下にdyだけ進みながら、等間隔で星を10個並べるブロックを作ろう。このブロックを、変数 starLine で指すことにせよ。そして、starLine value: sx value: sy value: dx value: dy とメッセージを出して実行することにせよ。

(2) 次に、通常、星の色は黄色とするが、x 座標が 3 の倍数のときには、赤とするように改良せよ。ちなみに、割り算の余りは「\\(バックスラッシュ2つ)」の二項メッセージで求まる。値の一致を判定するには「==(イコール2つ)」の二項メッセージを使う。

このブロックを実現するために、サブルーチンとなるブロックを作成しても構わない。

レポートには、改良後の starLine と関連プログラム、および、実行結果のスクリーンショット(練習2の解答例のようなもの)を印刷したものに、手書きで要所にコメントを記載せよ。

来週、演習の開始時に集めます。


(C) 2009.4.22 by tokuhisa