WEBVTT

00:00:00.560 --> 00:00:04.040 align:middle
この講義では高度な機能を
もう 1 つ探検します。

00:00:04.200 --> 00:00:07.080 align:middle
オンデマンドで実行スタックを

00:00:07.280 --> 00:00:10.560 align:middle
オブジェクトに変換する方法を
見せたいと思います。

00:00:11.200 --> 00:00:15.600 align:middle
あまり細部には触れません。
直感的な道具立てとするのが目的です。

00:00:17.080 --> 00:00:19.840 align:middle
スタックを操作して
ナビゲーションしたり

00:00:20.040 --> 00:00:23.160 align:middle
変更したりできますが
今回はナビゲーションに焦点を合わせます。

00:00:23.600 --> 00:00:28.400 align:middle
この話題についての読み物として
本の中で 2 つの章があります。

00:00:28.640 --> 00:00:31.640 align:middle
ブロックに関する章と

00:00:31.840 --> 00:00:35.080 align:middle
例外に関する章が
Deep into Pharo という本にあります。

00:00:35.280 --> 00:00:39.280 align:middle
明快な説明がされていて
読む価値があるものです。

00:00:39.520 --> 00:00:43.400 align:middle
Pharo では Context クラスも
スタックを表現します。

00:00:44.600 --> 00:00:45.600 align:middle
さてと

00:00:46.280 --> 00:00:50.160 align:middle
デバッガの中でコーディングする
シナリオを使います。

00:00:50.400 --> 00:00:55.000 align:middle
ユニットテストを実行した時に

00:00:55.200 --> 00:00:57.520 align:middle
送ったメッセージが未定義のために
見つからなかったとします。

00:00:57.840 --> 00:01:02.720 align:middle
そのメソッドを作るように
デバッガに言って

00:01:02.920 --> 00:01:06.040 align:middle
コンパイルして
クラスにインストールします。

00:01:06.200 --> 00:01:07.920 align:middle
そして再実行します。

00:01:08.080 --> 00:01:12.560 align:middle
このメソッドは例外を上げます。
このシステムは魔法ではないので。

00:01:12.720 --> 00:01:16.200 align:middle
shouldBeImplemented メッセージが

00:01:16.360 --> 00:01:19.440 align:middle
デバッガでそのメソッドを編集するように
促してきます。

00:01:19.640 --> 00:01:21.440 align:middle
そのメソッドを実装して

00:01:21.840 --> 00:01:26.000 align:middle
その場で再コンパイルして
「Proceed」を選んで

00:01:26.600 --> 00:01:28.080 align:middle
プログラムを継続実行させます。

00:01:28.920 --> 00:01:32.360 align:middle
このシナリオには
2 つのキーポイントがあります。

00:01:32.920 --> 00:01:36.280 align:middle
1 つ目は、メソッドをオンザフライで
再コンパイルしたこと。

00:01:36.640 --> 00:01:40.080 align:middle
何度もやりますが
それはコンパイラの仕事です。

00:01:40.920 --> 00:01:44.920 align:middle
2 つ目は、これが重要ですが
実行スタックを書き換えて

00:01:45.080 --> 00:01:48.840 align:middle
スタック上に
新しいチャンクを挿入します。

00:01:49.040 --> 00:01:53.200 align:middle
そうすることでエラーの後でも
プログラムを継続実行できます。

00:01:53.440 --> 00:01:58.600 align:middle
単にスタックを具体化（レイフィケーション）
してオブジェクトにするだけでなく

00:01:58.760 --> 00:02:03.640 align:middle
形の上での演習でもなく
ユーザ体験を向上させたり

00:02:03.920 --> 00:02:05.560 align:middle
新しいツールを作ることができます。

00:02:05.720 --> 00:02:10.640 align:middle
ウェブアプリケーションを作る
Seaside でも使われています。

00:02:11.080 --> 00:02:15.720 align:middle
Pharo は通常は C のスタックを持っています。
仮想機械のスタックです。

00:02:16.040 --> 00:02:19.360 align:middle
オンデマンドで、これを
ライブなオブジェクトに変換します。

00:02:19.520 --> 00:02:25.440 align:middle
興味深いのは、これを使って
ナビゲーションしたり修正できるのです。

00:02:25.760 --> 00:02:30.200 align:middle
ここでいう修正とは
この Pharo のオブジェクトを変化させると

00:02:30.400 --> 00:02:34.400 align:middle
直接手の届かない C のスタックも変化させる
とても強力なものです。

00:02:35.800 --> 00:02:41.280 align:middle
例外処理にも対応しています。
ぜひこれらの章を読むことを勧めます。

00:02:41.560 --> 00:02:44.080 align:middle
例外に対してスタックを辿っていって

00:02:44.440 --> 00:02:47.920 align:middle
キャッチブロックを探します。

00:02:49.920 --> 00:02:51.800 align:middle
いわゆる例外ハンドラです。

00:02:52.000 --> 00:02:57.200 align:middle
さらに、スタックをオブジェクトに
変換する能力は

00:02:57.400 --> 00:02:59.840 align:middle
Scheme のような
関数型言語にある継続や

00:03:00.040 --> 00:03:04.400 align:middle
ウェブサービスを可能にします。

00:03:05.320 --> 00:03:09.080 align:middle
どうやって動くのか説明するために
thisContext と呼ばれる変数を見ます。

00:03:09.200 --> 00:03:13.640 align:middle
Pharo の 3 つの擬似変数の 1 つです。

00:03:14.160 --> 00:03:17.360 align:middle
擬似変数は self と super と
thisContext です。

00:03:17.920 --> 00:03:22.600 align:middle
thisContext の値を得ようとすると
実行スタックが返ってきます。

00:03:22.920 --> 00:03:27.400 align:middle
デバッガを開くと見えるものです。

00:03:27.640 --> 00:03:31.840 align:middle
実行スタックは
thisContext に基づいて表示されます。

00:03:32.200 --> 00:03:36.280 align:middle
halt を挿入した

00:03:36.400 --> 00:03:39.360 align:middle
メソッドを定義すると

00:03:39.520 --> 00:03:44.400 align:middle
デバッガが開きます。
しかし、thisContext と入力して

00:03:45.440 --> 00:03:50.040 align:middle
インスペクターを開いても
実行スタックそのものが開きます。

00:03:50.600 --> 00:03:53.800 align:middle
thisContext を使う例を

00:03:53.920 --> 00:03:56.400 align:middle
2 つお見せしましょう。

00:03:56.680 --> 00:04:02.360 align:middle
1 つ目はデプリケーションです。
API を変更したい時に使います。

00:04:02.640 --> 00:04:08.560 align:middle
プログラマはメソッドで
deprecated: メッセージを

00:04:08.720 --> 00:04:13.640 align:middle
on:in: 付きで使います。
例外の講義で説明しました。

00:04:14.680 --> 00:04:19.760 align:middle
ここでは、「Use bar」という
メッセージを示したいわけですが

00:04:20.080 --> 00:04:23.840 align:middle
デプリケーションは

00:04:24.000 --> 00:04:26.840 align:middle
ユーザに

00:04:27.040 --> 00:04:30.200 align:middle
「Message foo is deprecated in Pharo.」
と表示します。

00:04:30.360 --> 00:04:33.920 align:middle
ここで大事な点は

00:04:34.200 --> 00:04:36.600 align:middle
どのメソッドがデプリケーションの対象か
宣言しなかってにも関わらず

00:04:36.840 --> 00:04:40.920 align:middle
deprecated: を呼び出したのは
foo だとシステムが特定したことです。

00:04:42.080 --> 00:04:46.640 align:middle
見ての通り、deprecated:の引数には
メソッドを呼び出している

00:04:47.320 --> 00:04:48.920 align:middle
foo は与えられていません。

00:04:49.080 --> 00:04:51.840 align:middle
では、どうやって実装されているのでしょう？

00:04:52.600 --> 00:04:54.280 align:middle
deprecated: メッセージは

00:04:55.920 --> 00:04:58.040 align:middle
Deprecation 例外をあげます。

00:04:58.200 --> 00:05:03.160 align:middle
引数として anExplanationString
などを渡します。

00:05:03.320 --> 00:05:07.800 align:middle
そして、この表現式が追加されています。
thisContext sender method

00:05:08.160 --> 00:05:13.920 align:middle
thisContext は deprecated: メソッドを
実行中のスタックです。

00:05:15.720 --> 00:05:19.320 align:middle
そして sender を使って
メソッドを呼び出した側にアクセスできます。

00:05:20.000 --> 00:05:23.200 align:middle
すると foo が得られます。
つまりこの例題です。

00:05:23.600 --> 00:05:25.560 align:middle
そしてメソッドを求めます。

00:05:25.720 --> 00:05:29.800 align:middle
thisContext sender method
はコンパイル済みのメソッドを返します。

00:05:29.920 --> 00:05:31.640 align:middle
それはオブジェクトで

00:05:31.800 --> 00:05:35.080 align:middle
A>>foo という名前です。

00:05:35.280 --> 00:05:39.720 align:middle
こうしてこの例外は
メソッドのセレクタを得て

00:05:39.920 --> 00:05:43.840 align:middle
より明確なメッセージを作ります。

00:05:44.280 --> 00:05:49.600 align:middle
プログラマにそのメッセージの元を
ハードコードさせることなく

00:05:49.800 --> 00:05:54.040 align:middle
ユーザーが理解しやすい
メッセージを作ることができます。

00:05:54.320 --> 00:05:59.040 align:middle
では、もう 1 つの
強力な機能をお見せしましょう。

00:06:01.640 --> 00:06:05.280 align:middle
デバッグをしている時には
激しく使われているメソッドに

00:06:05.400 --> 00:06:08.760 align:middle
ブレークポイントを挿入することが
よくあります。

00:06:09.360 --> 00:06:13.320 align:middle
システム全体を止めることなしに

00:06:13.440 --> 00:06:15.720 align:middle
自分のプログラムだけをデバッグ
したいわけです。

00:06:15.920 --> 00:06:21.040 align:middle
haltOnce のような条件は
システムを一度だけ停止させますが

00:06:21.200 --> 00:06:25.680 align:middle
やりたいことはそうではなく
そのメソッドがある別のメソッドから

00:06:25.920 --> 00:06:29.000 align:middle
呼ばれた時だけ halt したいわけです。

00:06:29.640 --> 00:06:32.840 align:middle
プログラマは
どう表現したらいいでしょう？

00:06:33.040 --> 00:06:37.400 align:middle
testSetInitialized メソッドから

00:06:37.600 --> 00:06:40.520 align:middle
foo が呼ばれたならば
halt というわけです。

00:06:41.520 --> 00:06:44.280 align:middle
どう実装されているのでしょう。

00:06:44.440 --> 00:06:47.200 align:middle
通常、このメソッドは停止してはいけません。

00:06:47.760 --> 00:06:52.760 align:middle
Pharo でコードを開いて
どう実装されているか見ることができます。

00:06:52.920 --> 00:06:54.840 align:middle
Halt は例外クラスです。

00:06:55.400 --> 00:06:57.640 align:middle
if: メッセージを見ます。

00:06:57.840 --> 00:07:00.160 align:middle
引数の場合分けがいくつかあります。

00:07:00.320 --> 00:07:05.080 align:middle
シンボルの場合について
まずシンボルかどうか問い合わせた上で

00:07:05.320 --> 00:07:10.200 align:middle
コールチェインの中にそのシンボルが
含まれていないかを見ます。

00:07:10.400 --> 00:07:11.400 align:middle
では確認してみましょう。

00:07:12.360 --> 00:07:15.360 align:middle
そのメソッドを見てみます。

00:07:16.000 --> 00:07:19.800 align:middle
testSetInitialized という名前の

00:07:20.840 --> 00:07:22.200 align:middle
テストがあるとします。

00:07:23.800 --> 00:07:25.280 align:middle
その名前がここの引数です。

00:07:26.200 --> 00:07:31.400 align:middle
まず、メソッドは実行スタック

00:07:32.720 --> 00:07:35.560 align:middle
つまりコンテキストを引き出します。

00:07:35.760 --> 00:07:41.080 align:middle
コンテキストを使って
スタックにアクセスします。

00:07:41.200 --> 00:07:44.920 align:middle
今は実行スタックの
トップではありません。

00:07:45.160 --> 00:07:48.080 align:middle
トップでは呼び出す側の
センダーがありません。

00:07:48.440 --> 00:07:52.280 align:middle
スタックのトップでは
センダーは nil になります。

00:07:52.600 --> 00:07:56.160 align:middle
センダーが nil ではない場合には

00:07:56.520 --> 00:07:59.400 align:middle
スタックを移動していきます。

00:07:59.560 --> 00:08:02.920 align:middle
スタックの領域を絵に描くと
こんな感じになっていて

00:08:03.200 --> 00:08:06.040 align:middle
sender を使って
上のほうにいきます。

00:08:06.840 --> 00:08:07.920 align:middle
1 つずつ。

00:08:09.080 --> 00:08:12.080 align:middle
ここでセレクターを
見ていく必要があります。

00:08:12.200 --> 00:08:15.520 align:middle
この領域のどこかに
テストがあるはずです。

00:08:16.680 --> 00:08:18.320 align:middle
もしスタックのコールシンボルが

00:08:18.840 --> 00:08:23.080 align:middle
停止対象にしたいものと
マッチしているか見ていきます。

00:08:23.200 --> 00:08:26.400 align:middle
testSet…から呼ばれていないか
チェックしていきます。

00:08:26.640 --> 00:08:31.200 align:middle
該当していたら、そこで signal します。
このクラスは例外クラスですから。

00:08:32.000 --> 00:08:36.320 align:middle
重要なのは、スタックの具体化を
しない言語でこれを実装することは

00:08:36.440 --> 00:08:39.760 align:middle
難しいということを
理解することです。

00:08:40.080 --> 00:08:44.640 align:middle
ここでは 5 行です。理解するのは
大変そうに見えるかもしれませんが。

00:08:44.840 --> 00:08:49.560 align:middle
コンパクトで強力で
具体化を通してのみ可能なのです。

00:08:50.160 --> 00:08:55.640 align:middle
thisContext は高度な機能なので
多くは使われません。

00:08:55.920 --> 00:08:59.160 align:middle
しかしツールなど新しいものを
創造する上で重要なものです。

00:08:59.320 --> 00:09:02.080 align:middle
これらのテストで見たように

00:09:02.840 --> 00:09:05.560 align:middle
この言語ではサポートされています。

00:09:05.720 --> 00:09:09.080 align:middle
継続を表現するためにも使われます。

00:09:09.400 --> 00:09:12.600 align:middle
Seaside を創った人は
継続を表現するために

00:09:12.760 --> 00:09:16.280 align:middle
スタックを操作するために
Pharo の先祖にあたる言語を使いました。

00:09:16.400 --> 00:09:21.840 align:middle
これは Seaside のコールアンサーの
基礎になっています。

00:09:22.280 --> 00:09:27.280 align:middle
Pharo のこの高度な機能を
いじり回してみましょう。

