1 00:00:00,520 --> 00:00:03,880 このセッションでは メッセージの合成を学びます。 2 00:00:04,040 --> 00:00:08,720 優先順位がどのように働くか 階層を見ます。 3 00:00:08,880 --> 00:00:11,600 まず問題ですが 4 00:00:11,760 --> 00:00:15,080 「単項メッセージのシーケンスがある場合には 何が起こるでしょうか?」 5 00:00:15,240 --> 00:00:18,040 次のような表現式があるとします。 6 00:00:18,200 --> 00:00:20,720 1000 factorial class name 何が起こるでしょう? 7 00:00:20,880 --> 00:00:24,400 これらの括弧があるのと同じように 実行されます。 8 00:00:24,560 --> 00:00:26,680 見ての通り煩雑ですね。 9 00:00:26,840 --> 00:00:30,840 同じレベルのメッセージが複数ある場合 10 00:00:31,000 --> 00:00:35,000 (単項、二項またはキーワードの いずれでも同じです) 11 00:00:35,160 --> 00:00:37,320 左から右に評価されていきます。 12 00:00:37,480 --> 00:00:40,280 まず 1000 に factorial メッセージ(階乗) を送ります。 13 00:00:40,440 --> 00:00:43,960 そして factorial の結果に対して class メッセージを送ります。 14 00:00:44,120 --> 00:00:46,600 そしてこの新しいオブジェクトに 15 00:00:47,800 --> 00:00:50,600 name メッセージが投げられます。 16 00:00:50,760 --> 00:00:52,880 LargePositiveInteger が返ってきます。 17 00:00:53,640 --> 00:00:56,080 1000の階乗(factorial)は大きな数です。 18 00:00:56,240 --> 00:00:59,320 10000の階乗を試すこともできます。 19 00:00:59,920 --> 00:01:01,160 するとさらにもう少し「長い」数になります。 20 00:01:02,160 --> 00:01:06,160 括弧つきのメッセージもあります。 21 00:01:06,320 --> 00:01:08,520 先に実行される必要がある時です。 22 00:01:08,680 --> 00:01:11,960 次に単項メッセージ、次に二項メッセージ その次にキーワードメッセージです。 23 00:01:12,120 --> 00:01:15,200 同じレベルの場合には 左から右へ行きます。 24 00:01:15,920 --> 00:01:17,720 1つ例題をやってみましょう。 25 00:01:17,880 --> 00:01:21,800 単項メッセージ squared と 26 00:01:21,960 --> 00:01:24,480 二項メッセージ + があります。 27 00:01:24,640 --> 00:01:27,000 単項メッセージが勝ちます。 28 00:01:27,160 --> 00:01:30,800 まず squared を送信して 29 00:01:30,960 --> 00:01:33,760 次に + メッセージを送信します。 30 00:01:33,920 --> 00:01:36,640 11が返ってきます。正解です。 31 00:01:37,480 --> 00:01:39,560 別の状況があります。 32 00:01:39,720 --> 00:01:42,360 raisedTo: メッセージで累乗を求めます。 33 00:01:42,520 --> 00:01:47,040 二項メッセージとキーワードがあります。 二項メッセージが勝ちます。 34 00:01:47,200 --> 00:01:49,520 まず 5 が得られ 35 00:01:49,680 --> 00:01:53,080 そして raisedTo: が実行され 32が返ってきます。 正解です。 36 00:01:54,000 --> 00:01:56,160 これはもう少し複雑な例です。 37 00:01:56,320 --> 00:02:00,120 Pharo では色はオブジェクトです。 38 00:02:00,280 --> 00:02:01,680 Color クラスがあります。 39 00:02:01,840 --> 00:02:06,240 3つの単項メッセージがあります。 gray と white と black です。 40 00:02:06,400 --> 00:02:11,360 2つの二項メッセージがあります。 = と - です。 41 00:02:11,520 --> 00:02:16,160 では何が起こるでしょう? システムはまず各単項メッセージを実行します。 42 00:02:16,840 --> 00:02:21,320 それぞれ灰色、白、黒の オブジェクトを返します。 43 00:02:21,480 --> 00:02:25,080 そしてメッセージを送ります。 44 00:02:25,240 --> 00:02:28,560 - メッセージと = メッセージから 選ばなければなりません。 45 00:02:29,520 --> 00:02:34,480 灰色オブジェクトに - メッセージを 白を引数として送ります。 46 00:02:34,640 --> 00:02:36,800 黒が返ってきます。 47 00:02:37,520 --> 00:02:41,520 2つの色を比較します。 黒 = 黒になります。trueです。 48 00:02:43,320 --> 00:02:46,160 この例題は 49 00:02:47,360 --> 00:02:50,200 Pharoで自動変換ができるというもので 50 00:02:50,360 --> 00:02:52,880 ある種の冗談です。 51 00:02:53,960 --> 00:02:57,960 この表現式です。 1 class maxVal + 1 52 00:02:58,120 --> 00:03:00,920 2つの単項メッセージがあります。 class と maxVal です。 53 00:03:01,080 --> 00:03:02,400 そして二項メッセージが1つです。 54 00:03:03,640 --> 00:03:05,720 この表現式はどう実行されるでしょうか? 55 00:03:05,880 --> 00:03:08,800 小さな整数 1 に class メッセージを送ります。 56 00:03:08,960 --> 00:03:12,760 SmallInteger が返ってきます。 1 は整数ですから。正しいです。 57 00:03:13,560 --> 00:03:18,840 1 class の結果である SmallInteger に maxVal メッセージを送ります。 58 00:03:19,000 --> 00:03:20,800 maxVal メッセージとは何でしょう? 59 00:03:20,960 --> 00:03:25,560 「あなた(SmallInteger)が符号化できる 最大の数は何ですか?」という意味です。 60 00:03:25,720 --> 00:03:29,960 この大きな数が得られます。 この、最後が23で終わる数です。 61 00:03:30,960 --> 00:03:36,120 この数に + 1 メッセージを送ります。 62 00:03:36,920 --> 00:03:40,160 返ってくるのは小さな整数(SmallInteger) ではありません。 63 00:03:40,320 --> 00:03:44,240 なぜなら、SmallIntegerで表現できる 最大の数がこれだからです。 64 00:03:44,400 --> 00:03:47,080 結果として 答えはSmallIntegerにはできません。 65 00:03:47,240 --> 00:03:51,440 この数のクラスが何かを知りたいです。 66 00:03:51,960 --> 00:03:56,480 括弧で囲んで、class を送ります。 LargePositiveInteger が返ってきます。 67 00:03:56,640 --> 00:04:00,160 これが最大のSmallIntegerで 68 00:04:00,320 --> 00:04:02,840 これが最小のLargePositiveIntegerです。 69 00:04:04,280 --> 00:04:06,280 括弧で囲むのは 70 00:04:06,440 --> 00:04:09,480 それがないと class は 1 に送られてしまうからです。 71 00:04:09,640 --> 00:04:12,760 それでは困ります。 結果に対して class を送りたいのです。 72 00:04:14,520 --> 00:04:18,640 矩形を生成したとします。 73 00:04:18,800 --> 00:04:22,120 その矩形の右下の点が欲しい時に 74 00:04:22,280 --> 00:04:24,640 こう書くと 実行するとクラッシュします。 75 00:04:24,800 --> 00:04:29,080 システムは理解できません。 100 は bottomRight を理解できません。 76 00:04:29,240 --> 00:04:33,680 なぜ? bottomRightは単項メッセージなので 77 00:04:33,840 --> 00:04:38,560 他のメッセージよりも先に実行されます。 bottomRightはレシーバーである100に送られます。 78 00:04:38,720 --> 00:04:42,520 100 はこの API を理解できません。 なぜなら 100 は Rectangle(矩形)ではないからです。 79 00:04:42,680 --> 00:04:46,360 この表現式のように 括弧で囲まなければなりません。 80 00:04:46,520 --> 00:04:50,440 どのように動くのでしょう? 括弧で囲まれたものが先に実行されます。 81 00:04:50,600 --> 00:04:55,880 内側では2つの二項メッセージがあり それらが実行されます。 82 00:04:56,040 --> 00:04:58,960 2つの点が生成されます。 83 00:04:59,120 --> 00:05:02,360 そして extent: メッセージを送ります。 矩形を作る一方の点に送ります。 84 00:05:02,520 --> 00:05:05,120 点 0@0 があります。 85 00:05:05,280 --> 00:05:09,880 extent:メッセージに広がり 100@100 を渡します。 86 00:05:10,440 --> 00:05:12,080 この矩形が返ってきます。 87 00:05:12,240 --> 00:05:15,680 それに bottomRight の値を尋ねます。 88 00:05:15,840 --> 00:05:17,200 矩形の 89 00:05:17,360 --> 00:05:20,480 ここの点の値を返してきます。 90 00:05:20,640 --> 00:05:23,400 100@100 です。 91 00:05:24,960 --> 00:05:28,600 Pharo では色々な事がシンプルだと これまで言ってきました。 92 00:05:28,760 --> 00:05:30,360 メッセージしかありません。 93 00:05:30,520 --> 00:05:34,560 + はメッセージです。他と同様。 優先順位はありません。 94 00:05:34,720 --> 00:05:38,400 + をDSL(ドメイン特化言語)に使えるのは 良いことです。 95 00:05:38,560 --> 00:05:42,920 + を数学的なオブジェクトとは関係ない オブジェクト間に使うことができます。 96 00:05:43,080 --> 00:05:47,200 Java ではこれはできません。 C++ では演算子を再定義することで可能です。 97 00:05:47,360 --> 00:05:49,760 Pharo では 98 00:05:49,920 --> 00:05:53,200 + は他のメッセージと同じ扱いにすると 決めることで解決しています。 99 00:05:53,360 --> 00:05:55,280 強調すべきはシンプルさです。 100 00:05:55,440 --> 00:05:58,880 代償があります。 数学的な結合順位がありません。 101 00:05:59,040 --> 00:06:00,960 例を見てみましょう。 102 00:06:02,160 --> 00:06:05,640 この表現式では 2つの演算子があります。 103 00:06:05,800 --> 00:06:08,480 2つの二項メッセージです。 104 00:06:08,640 --> 00:06:10,560 左から右に実行されます。 105 00:06:11,720 --> 00:06:15,480 5 が得られ、50が返ってきます。 学校で習ったのとは違います。 106 00:06:15,640 --> 00:06:19,440 これを解決するためには 括弧で囲む必要があります。 107 00:06:19,600 --> 00:06:21,200 * を括弧で囲みます。 108 00:06:21,360 --> 00:06:26,400 Pharo で算術演算子を使う時には 注意が必要です。 109 00:06:26,560 --> 00:06:29,520 数学的演算子はメッセージにすぎないからです。 110 00:06:30,040 --> 00:06:31,160 もう1つの例です。 111 00:06:31,320 --> 00:06:34,800 1/3 + 2/3 と書くと 正しい答えが得られません。 112 00:06:34,960 --> 00:06:38,640 システムがこの式を先に実行するからです。 113 00:06:39,160 --> 00:06:41,120 左から右へ実行されるからです。 114 00:06:41,280 --> 00:06:43,840 括弧で囲むと 正しい結果が得られます。 115 00:06:44,000 --> 00:06:46,640 興味深い点を1つ挙げると 116 00:06:46,800 --> 00:06:49,960 (1/3) + (2/3) と書くと 整数の 1 が得られます。 117 00:06:50,120 --> 00:06:54,280 1.000... や 0.999... ではありません。 118 00:06:54,440 --> 00:06:59,440 正確な分数の操作を行います。 正確な計算結果が得られます。 119 00:06:59,600 --> 00:07:01,200 まとめると 120 00:07:01,360 --> 00:07:05,600 メッセージには3種類あります。 もう知っている筈です。 121 00:07:05,760 --> 00:07:07,560 単項、二項、そしてキーワードです。 122 00:07:07,720 --> 00:07:11,040 まず最初に括弧が実行されます。 123 00:07:11,200 --> 00:07:13,320 そして単項、二項、そしてキーワードです。 124 00:07:13,480 --> 00:07:16,120 同じレベルの場合には 125 00:07:16,280 --> 00:07:20,480 例えば2つの単項メッセージがある場合には 左から右に進みます。 126 00:07:20,640 --> 00:07:23,320 数学的な結合順位はありません。 127 00:07:23,480 --> 00:07:26,480 数学的な演算子も単なるメッセージです。 128 00:07:26,640 --> 00:07:29,280 多くの言語と異なるのは 129 00:07:29,440 --> 00:07:34,160 引数がメッセージの構造の中に置かれることです。 例えば between:and: です。