前回、SmalltalkのコードとScratchのブロックの対応をさせて説明しました。
100 timesRepeat:[
(self owner isKindOf: HandMorph) ifTrue:[
self append: self xpos toList: 'paths-x'.
self append: self ypos toList: 'paths-y'
].
(Delay forMilliseconds: 100) wait
]
「"x座標"を"paths-x"に追加する」というブロックが、3行目のself append: self xpos toList: 'paths-x'
に対応します。
今回は、ブロックから対応するSmalltalkの処理を調べる方法を紹介します。
(Smalltalkを使えるようにする方法やハロの出し方等はこちらを参照)
レシーバとセレクタ
以降の手順を理解するためにレシーバとセレクタという概念を理解する必要が有ります。ここでSmalltalkの文法を簡単に説明します。
Smalltalkはオブジェクトにメッセージを送ることでプログラムを記述します。レシーバ(receiver)はメッセージを受け取るオブジェクトで、セレクタ(selector)はメッセージの種類です。例えば、self xpos
というコードでは、レシーバはself
、セレクタはxpos
になります。
セレクタの最後にコロン(:)が付いている場合、追加の情報を加えてメッセージを送ることもできます。Transcript show: 'recording...'
というコードでは、Transcript
というオブジェクトにshow:
というセレクタで、'recording...'
という文字列を追加の情報として送っています。この追加の情報を引数(arguments)と言います。
セレクタに含まれるコロンの数だけ引数を渡します。append:toList:
は2つの引数を渡すセレクタであり、self append: 100 toList: 'paths-x'
というコードを書くと、self
というレシーバに対し100
と'paths-x'
という引数を渡すことになります。
これまで、登場したSmalltalkのコードのレシーバ、セレクタは下記のようになります。
self xpos " → レシーバはself、セレクタはxpos、引数なし"
Transcript show: 'recording.' " → レシーバはTranscript、セレクタはshow:、引数は'recording.'"
self append: 100 toList: 'paths-x' " → レシーバはself、セレクタはappend:toList:、引数は100と'paths-x'"
(Delay forMilliseconds: 100) wait " → レシーバは(Delay forMilliseconds: 100)、セレクタはwait"
手順
-
リストに値を追加するブロックにハロを表示して、レンチアイコンからinspect morphを選択します。("CommandBlock"と表示されます)
-
インスペクタの画面上部左側の枠を少し下にスクロールさせて、"receiver"と"selector"の値を確認します。
"receiver"は"a ScratchSpriteMorph"、"selector"は"#append:toList:"と表示されるはずです。
-
手順2.で確認したブロックのオブジェクトが持っていたreceiverとselectorはブロックが実行されると、どのレシーバに対して、どのセレクタでメッセージを送るかの情報になります。今回の例ではスプライトのオブジェクト( ScratchSpriteMorphクラスのオブジェクト)に対して、```append:toList:"というセレクタでメッセージを送ることになります。
-
先程の
append:toList:
のコードをシステムブラウザで見てみましょう。再度、"receiver"を選択してメニューを開き(Windowsの場合は右クリック、macはoption+クリック)、「browse full」を選択します(または、Alt/Command+b)。receiverのクラス(つまりScratchSpriteMorph)をシステムブラウザで開きます。
-
画面上部の右から2番目の枠の一番上の"-- all --"をクリックすると、一番右の枠にそのクラスが受け取れるセレクタの一覧が表示されます。
-
下の方にxpos(X座標を調べる時に使った)などはありますが、append:toList:はありません。クラスに無いセレクタが呼ばれた場合、その親クラスのセレクタを探します。クラスの親子関係を継承関係と言います。
-
クラスの継承関係を調べます。左から2番目の枠でScratchSpriteMorphを選択した状態になっているはずです。そのメニューを開き(Windowsの場合は右クリック、macの場合はoption+クリック)、"browse hierarchy"を選択します。
-
左側の枠に継承関係が表示されます。ScratchSpriteMorphの親はScriptableScratchMorphで、その親がMorph、さらにその親がObjectになっています。セレクタは一番下のクラスから順に親に向かって検索されます。append:toList:はScratchSpriteMorphにはないので、その親のScriptableScratchMorphにそのセレクタが定義されているかを調べます。
-
左側の枠のScriptableScratchMorphをクリックして、真ん中の枠の"-- all --"をクリックすると、一番右の枠にappend:toList:が現れます。画面下部に表示されているコードがScratchSpriteMorphクラスのオブジェクトに
append:toList:
を送った時に実行されます。 -
本当にブロックを実行するとこのコードが実行されるかを確認してみましょう。2行目に
self halt.
を追加してメニューからaccept(またはAlt/Command + s)します。
-
ブロックをクリックして実行すると、赤いウィンドウが表示され、停止します。「debug」をクリックしてデバッガを起動します。
-
デバッガの上段の枠の3つめをクリックします。先ほど追加した
self halt.
で停止しているはずです。デバッガの左下の枠から変数の値を確認することができます。
t1〜t3という変数があります。コードの一行めを見てみるとappend: t1 toList: t2
となっています。つまり、self append: (値) toList: '(変数名)'
というコードは最初の引数がt1
に、二つ目がt2
に入ることになります。 -
確認が終わったら、挿入した
self halt.
を削除してacceptして、元に戻します。
Smalltalk の学習のための資料
ここまででSmalltalkの基本的な概念やツールに触れてきましたが、自由にSmalltalkを扱えるようになるには一から理解を積み重ねることが大事です。
Smalltalkの教材はインターネット上にもいくつかありますが、Scratchを動かしているSmalltalkはかなり古いことに気をつけて下さい。見た目の違いや新しいSmalltalkにしかない機能があったりして戸惑うかもしれません。基本的な部分は同じなので、下記の資料が参考になるでしょう。
- Smalltalk基本文法編 (http://qiita.com/newapplesho/items/6376c90d3e9ca66d2a95)
- Smalltalk開発環境入門編 (http://qiita.com/newapplesho/items/4a90c0771e15506c8484)
- Smalltalk 基本クラス編 (http://qiita.com/newapplesho/items/323cf9d1be014861a57f)
- ドットインストール Smalltalk入門http://dotinstall.com/lessons/basic_smalltalk
動画でSmalltalkの解説が聞けます。 - 自由自在 Squeakプログラミング PDF版 (http://swikis.ddo.jp/squeak/13)
梅澤さんの著書のPDF版が無料で公開されています。