こんにちは。
今日は ifTrue:ifFalse: の 復習をします。
今までちゃんと講義に参加していれば （もちろん参加してきたと信じていますよ）
not の例題をやった時に気付いたはずです。
not と or と ifTrue:ifFalse: を実装できると言いましたが
正解として ifTrue:ifFalse: の実装を 示しませんでした。
この問題を今やってみましょう。
Pharo では条件分岐はメッセージです。
ここに例があります。
天気をあらわす Weather があります。 Weather isRaining
とすると、雨降りであれば
true となります。傘を持っていきます。
false ならばサングラスを持っていきます。
ifTrue:ifFalse: には
コロンが 2 つありますね？ つまり、キーワードメッセージです。
ifTrue:ifFalse: メッセージは キーワードメッセージで
真偽値のインスタンスに送られます。
実際にはコンパイラによって最適化されて 本当に送られているわけではないですが
概念的にいえば、メッセージを送ります。
ifTrue:ifFalse: を
再定義することは
Pharo では可能です。
これからその技術面を説明します。
ifTrue:ifFalse: メソッドは とても重要です。
とても速く動作する必要があります。
したがって関数を呼び出すのではなく
コンパイラがジャンプ命令を インライン展開します。
この講義ではifTrue:ifFalse:が どう機能するかを見るのが目的です。
あなたの実装を提案してください。
あなたはブロックを知っています。
True や False で
or や not をどう扱うのかを 知っています。
同じことを ifTrue:ifFalse: にも適用します。
この場合、もしレシーバーが false ならば 5 を返します。
レシーバーが true ならば 3 を返します。
繰り返しますが、オブジェクトと メッセージとブロックがあります。
くどいと思いますが そういうものです。
角括弧は表現式の実行を凍結して
value メッセージを受け取ると
凍結されたコードの実行を開始する
ということを覚えていますね。
これを使って さらに、not や or で
条件式を実装したように
ifTrue:ifFalse: を実装できるはずです。
数秒あげるので考えてみてください。
どうやって実装するかというと
or や not と同じ方法です。
True クラスに ifTrue:ifFalse:メソッドを定義して
引数を 2 つ取ります。
1 つは true の場合のブロックで もう 1 つは false の場合のブロックです。
これを使って
自分が True クラス に属していれば aTrueBlock を実行します。
自分が False クラスに属していれば
同じ引数の同じメソッドであっても
False クラスでは aFalseBlockを実行します。
Boolean での実装では
どうなっているかというと
こうなっています。
真偽値にメッセージを送ります。
ここで、その真偽値は true だとします。
ifTrue: [doTrue] ifFalse: [doFalse] を送ります。
すると ifTrue:ifFalse: を True クラスで探索します。
ここにあります。
aTBlock を実行しろとあるので 実行します。
同じメッセージを false に送ると
メソッドを探索して この ifTrue:ifFalse: が見つかります。
aFBlock を実行しろとあるので 実行します。
この実装をブレークポイントを置いて テストすることはできません。
最適化されているので システムがそれを受け付けません。
代わりに、同じ方法で
別のメソッド名で
実装してみてください。
ブレークポイントを使って
実験してみてください。
この例でお見せしたのは
メッセージを送って 正しいメソッドを選択することを使って
メッセージレシーバーに その振る舞いを決定させるということです。
また、角括弧で計算を凍結して
value が凍結されたコードの実行を 開始させます。