WEBVTT

00:00:00.440 --> 00:00:04.440 align:middle
このセッションでは、イテレータと
コレクションについてお話しします。

2 align:middle
00:00:04,600 --> 00:00:09,000
Pharo でイテレータによって
コレクションの中を列挙する方法を見てみましょう。

00:00:09.160 --> 00:00:13.000 align:middle
Pharo のイテレータの力がわかるでしょう。

00:00:13.160 --> 00:00:17.640 align:middle
よく使う主なイテレータを見てみましょう。

00:00:17.800 --> 00:00:19.360 align:middle
最初の例です。

00:00:19.520 --> 00:00:22.680 align:middle
これは Java で書いた

00:00:23.880 --> 00:00:25.320 align:middle
コレクションを列挙するコードです。

00:00:25.480 --> 00:00:28.160 align:middle
コレクション persons を列挙して

00:00:28.320 --> 00:00:31.920 align:middle
名簿を抽出します。

00:00:32.480 --> 00:00:35.240 align:middle
Pharo ではこのコードを書きます。

00:00:35.400 --> 00:00:39.880 align:middle
collect: イテレータを使います。
これについては後でお話しします。

00:00:40.040 --> 00:00:43.360 align:middle
人々の全ての名前を集めます。

00:00:43.520 --> 00:00:47.920 align:middle
ところで、Java の最新版の Java 8 では

00:00:48.080 --> 00:00:51.120 align:middle
レキシカルクロージャを導入しました。

00:00:51.280 --> 00:00:53.640 align:middle
ブロックと等価なものです。

00:00:53.800 --> 00:00:57.000 align:middle
その結果、構文が Pharo に近付きました。

00:00:57.160 --> 00:01:00.200 align:middle
しかし、Pharo では
最初からブロックがありました。

00:01:00.360 --> 00:01:02.440 align:middle
ブロックはこの言語の心臓部です。

00:01:02.600 --> 00:01:07.320 align:middle
プログラマにとても大きな表現力を
与えます。

00:01:08.200 --> 00:01:11.320 align:middle
とても多くのイテレータがあります。

00:01:11.480 --> 00:01:16.400 align:middle
まず collect: があります。コレクションに
collect: を送ることで何ができるでしょうか？

00:01:16.560 --> 00:01:20.240 align:middle
これは正や負の数のコレクションです。

00:01:20.400 --> 00:01:23.200 align:middle
collect: メッセージを送って
ブロックを渡します。

00:01:23.360 --> 00:01:25.560 align:middle
コレクションを列挙する時は

00:01:25.720 --> 00:01:30.160 align:middle
順番にブロックの引数になります。
2, -3, 4, …という具合に。

00:01:30.320 --> 00:01:33.760 align:middle
そして abs メッセージを送って
絶対値を求めます。

00:01:33.920 --> 00:01:36.840 align:middle
abs メッセージはこの数の絶対値が
欲しいという意味です。

00:01:37.000 --> 00:01:40.720 align:middle
コレクションのそれぞれの要素に対して
ブロックを適用したら

00:01:40.880 --> 00:01:43.360 align:middle
結果が新しいコレクションに集約されます。

00:01:43.520 --> 00:01:46.520 align:middle
collect: に返される結果は
新しいコレクションです。

00:01:46.680 --> 00:01:50.160 align:middle
ブロックがコレクションの各要素に
適用されています。

00:01:50.320 --> 00:01:53.800 align:middle
2 の絶対値
-3 の絶対値つまり 3

00:01:53.960 --> 00:01:58.480 align:middle
4 の絶対値の 4
-35 の絶対値の 35

00:01:58.640 --> 00:02:00.320 align:middle
そして 4 の絶対値の 4

00:02:01.080 --> 00:02:04.200 align:middle
覚えておいておくべきことは

00:02:04.360 --> 00:02:06.760 align:middle
オブジェクトで考えるということです。

00:02:06.920 --> 00:02:09.720 align:middle
コレクションに何かをするようにお願いします。

00:02:09.880 --> 00:02:14.440 align:middle
コレクションは自分で
その要素を列挙します。

00:02:14.600 --> 00:02:17.240 align:middle
各要素への処理を与えます。

00:02:17.400 --> 00:02:20.400 align:middle
これがイテレータの大事な部分です。

00:02:21.040 --> 00:02:23.280 align:middle
これは collect: の別の例です。

00:02:23.440 --> 00:02:27.000 align:middle
このコレクションに
collect: メッセージを送ります。

00:02:27.160 --> 00:02:31.000 align:middle
ブロックでは毎回

00:02:31.760 --> 00:02:34.200 align:middle
要素が奇数か尋ねます。

00:02:34.360 --> 00:02:37.160 align:middle
その結果を全て集約します。

00:02:37.320 --> 00:02:40.080 align:middle
false、true、false、true、と。

00:02:43.720 --> 00:02:47.480 align:middle
もちろん

00:02:47.640 --> 00:02:50.400 align:middle
他の言語でやるように

00:02:50.560 --> 00:02:52.680 align:middle
ブロックやイテレータを使わずに
書くこともできます。

00:02:52.840 --> 00:02:55.160 align:middle
コレクションがあり

00:02:55.760 --> 00:02:58.680 align:middle
結果のコレクションを作り

00:02:59.320 --> 00:03:03.560 align:middle
1 から コレクションの大きさまで
整数を列挙します。

00:03:03.720 --> 00:03:04.960 align:middle
to:do: を使います。

00:03:05.120 --> 00:03:08.920 align:middle
コレクションを列挙して
result コレクションに追加していきます。

00:03:09.080 --> 00:03:12.400 align:middle
こうやって書くこともできます。
全く同じことです。

00:03:12.560 --> 00:03:15.440 align:middle
あなた次第です。
シンプルに書きたいのか

00:03:15.600 --> 00:03:19.000 align:middle
それとも、ややこしく書きたいか。
それだけの話です。

00:03:19.160 --> 00:03:22.000 align:middle
私はシンプルなやり方のほうが断然良いです。

00:03:24.200 --> 00:03:27.120 align:middle
Pharo のコレクションの階層では

00:03:28.320 --> 00:03:32.000 align:middle
全てのコレクションは多相的で

00:03:32.160 --> 00:03:35.080 align:middle
Collectionクラスを継承しています。
つまり、共通の API があります。

00:03:35.240 --> 00:03:39.720 align:middle
長所として、大部分のコレクションで

00:03:39.880 --> 00:03:42.840 align:middle
同じイテレータを使えます。

00:03:44.480 --> 00:03:48.080 align:middle
それがオブジェクトで考えるということです。

00:03:48.240 --> 00:03:51.280 align:middle
コレクションに
自分の中身を列挙するように言います。

00:03:51.440 --> 00:03:54.800 align:middle
言った側は Dictionary（辞書）を
使っているのかどうかも、わかりません。

00:03:54.960 --> 00:03:58.880 align:middle
我々はキーや値がどうしたという
内部的なロジックを知りたくはありません。

00:03:59.400 --> 00:04:02.320 align:middle
だからコレクションに行儀よくお願いして

00:04:02.480 --> 00:04:04.960 align:middle
その要素を処理してもらうのです。

00:04:06.640 --> 00:04:11.320 align:middle
沢山のイテレータが使えます。
do: と collect: はもう見ましたね。

00:04:11.480 --> 00:04:14.280 align:middle
他にももっとあります。
select:、 reject:、 detect:、などなど。

00:04:14.440 --> 00:04:17.840 align:middle
このコースではそのうちいくつかを
後で学びます。

00:04:19.320 --> 00:04:22.760 align:middle
do: は最も単純なイテレータです。

00:04:22.920 --> 00:04:26.960 align:middle
do: はコレクションの各要素を列挙します。
トランスクリプトに表示します。

00:04:27.120 --> 00:04:30.560 align:middle
もう何度も勉強しましたね。

00:04:30.720 --> 00:04:33.320 align:middle
新しいイテレータがあります。select: です。

00:04:33.480 --> 00:04:36.560 align:middle
コレクションの要素のうち

00:04:36.720 --> 00:04:38.360 align:middle
条件に合ったもの全てを得ます。

00:04:38.520 --> 00:04:41.960 align:middle
コレクションの要素のうち
奇数のものを得ます。

00:04:42.120 --> 00:04:45.040 align:middle
このコレクションに select: を送ります。

00:04:45.200 --> 00:04:46.440 align:middle
ブロックを渡します。

00:04:46.600 --> 00:04:49.560 align:middle
ブロックの値が true であれば

00:04:49.720 --> 00:04:53.080 align:middle
その要素は結果のコレクションに追加されます。

00:04:55.040 --> 00:04:58.080 align:middle
select: #odd と全く同じです。

00:04:58.240 --> 00:05:01.120 align:middle
ブロックの中で

00:05:01.280 --> 00:05:05.400 align:middle
ブロックの引数に単項メッセージを

00:05:05.560 --> 00:05:06.920 align:middle
送っているだけであれば

00:05:07.080 --> 00:05:10.760 align:middle
メッセージの名前をシンボルとして
渡すことができます。

00:05:10.920 --> 00:05:12.480 align:middle
このほうが、より短く書けます。

00:05:12.640 --> 00:05:16.000 align:middle
単項メッセージしか使えません。

00:05:17.920 --> 00:05:20.880 align:middle
他のイテレータとしては reject: があります。

00:05:21.040 --> 00:05:24.160 align:middle
このコレクションの要素のうち
奇数のものを取り除いたものを得ます。

00:05:24.320 --> 00:05:27.520 align:middle
結果として偶数のみが残っています。

00:05:28.520 --> 00:05:30.160 align:middle
また、detect: もあります。

00:05:30.320 --> 00:05:34.000 align:middle
条件に合う最初の要素を見つけます。

00:05:34.160 --> 00:05:37.000 align:middle
つまりブロックの値が true になるものです。

00:05:37.160 --> 00:05:40.920 align:middle
このコレクションの最初の奇数要素を得ます。
11 です。

00:05:42.320 --> 00:05:46.880 align:middle
条件に合う最初の要素が欲しいわけですが

00:05:47.040 --> 00:05:50.120 align:middle
条件に合うものが 1 つもない場合には
デフォルトが欲しくなります。

00:05:50.280 --> 00:05:52.440 align:middle
detect:ifNone: です。

00:05:52.600 --> 00:05:57.360 align:middle
もし条件に合うものがなければ
このブロックの値を返します。

00:05:57.520 --> 00:05:59.640 align:middle
この場合、0 です。

00:05:59.800 --> 00:06:04.800 align:middle
他にもプログラマを楽にしてくれる
イテレータがあります。

00:06:04.960 --> 00:06:06.800 align:middle
例えば、anySatisfy: です。

00:06:06.960 --> 00:06:10.600 align:middle
条件に合う要素が 1 つでもあるか確認します。

00:06:10.760 --> 00:06:13.320 align:middle
全ての要素が条件に合うか確認する
ことができます。

00:06:13.480 --> 00:06:17.320 align:middle
末尾から逆順にコレクションを列挙する
ことができます。

00:06:17.480 --> 00:06:22.360 align:middle
コレクションのインデックスと要素を列挙したり
要素を2つずつ列挙することもできます。

00:06:22.520 --> 00:06:26.480 align:middle
要素から全ての順列を列挙することができます。

00:06:26.640 --> 00:06:28.960 align:middle
沢山のイテレータがあります。

00:06:29.120 --> 00:06:31.480 align:middle
新しいイテレータを作ることもできます。

00:06:31.640 --> 00:06:35.320 align:middle
コレクション 1 2 3 を

00:06:35.480 --> 00:06:38.440 align:middle
もう 1 つのコレクションと一緒に
列挙します。

00:06:38.600 --> 00:06:42.600 align:middle
do: の引数のブロックには
:x と :y の 2 つの引数があります。

00:06:42.760 --> 00:06:46.840 align:middle
:x は1つ目のコレクションの要素

00:06:47.000 --> 00:06:48.920 align:middle
:y は2つ目のコレクションの要素です。

00:06:49.080 --> 00:06:51.080 align:middle
これらの要素を掛け算します。

00:06:51.240 --> 00:06:53.720 align:middle
結果は 10、40、90 です。

00:06:54.840 --> 00:06:59.440 align:middle
もちろん、このイテレータを使うには
コレクションの長さが同じでなければなりません。

00:07:01.360 --> 00:07:04.720 align:middle
他にもあります。

00:07:04.880 --> 00:07:08.120 align:middle
ここでは do:separatedBy: を使っています。

00:07:08.280 --> 00:07:11.280 align:middle
コレクションの各要素を列挙しますが

00:07:11.440 --> 00:07:14.040 align:middle
1つの要素を挙げる毎に

00:07:14.200 --> 00:07:17.680 align:middle
コンマを書き出すブロックを評価します。

00:07:17.840 --> 00:07:20.480 align:middle
つまり、a を挙げて

00:07:20.640 --> 00:07:23.320 align:middle
コンマを表示して、次に b で
次にコンマ、次に c となります。

00:07:23.480 --> 00:07:26.400 align:middle
各要素の間に
1つのアクションを実行します。

00:07:28.880 --> 00:07:31.640 align:middle
これは groupBy: イテレータです。

00:07:31.800 --> 00:07:36.040 align:middle
コレクションの要素を条件に従って

00:07:36.200 --> 00:07:37.720 align:middle
グループ分けします。

00:07:37.880 --> 00:07:42.040 align:middle
コレクション 1 2 3 4 5 6 7 に
このメッセージを送ります。

00:07:42.200 --> 00:07:45.480 align:middle
結果として辞書が得られます。

00:07:47.000 --> 00:07:50.440 align:middle
この #even という条件に対して

00:07:50.600 --> 00:07:52.800 align:middle
false だった全ての要素がこれです。

00:07:52.960 --> 00:07:56.000 align:middle
見ての通り
奇数の要素全てです。

00:07:56.160 --> 00:07:59.520 align:middle
偶数の要素はすべて true を返します。

00:08:02.280 --> 00:08:04.520 align:middle
よくあることですが

00:08:04.680 --> 00:08:07.720 align:middle
コレクションの中にコレクションを
入れ子にしがちです。

00:08:07.880 --> 00:08:11.440 align:middle
結果として深いレベルの入れ子になります。

00:08:11.600 --> 00:08:14.480 align:middle
これは手で作った例ですが

00:08:14.640 --> 00:08:17.560 align:middle
コレクションの中にコレクションが
入れ子になっています。

00:08:17.720 --> 00:08:22.200 align:middle
このコレクションをフラットにします。
それぞれの要素を引っ張り出して。

00:08:22.880 --> 00:08:26.960 align:middle
Pharo では簡単な方法があります。

00:08:27.120 --> 00:08:29.120 align:middle
flatCollect: イテレータです。

00:08:29.280 --> 00:08:33.520 align:middle
要素を列挙して
新しい平坦なコレクションを作ります。

00:08:35.240 --> 00:08:38.280 align:middle
コレクション 1 2 3 4 5 6 が得られます。

00:08:38.440 --> 00:08:40.600 align:middle
入れ子は無くなっています。

00:08:44.040 --> 00:08:48.520 align:middle
Pharo の全てのイテレータについて
説明するつもりはありません。

00:08:48.680 --> 00:08:52.480 align:middle
そんなことしたらダラダラと退屈なことになります。
ただ、沢山あるということはお見せしたいと思います。

00:08:52.640 --> 00:08:54.280 align:middle
コレクションのクラスを読んで

00:08:54.440 --> 00:08:57.760 align:middle
自分でイテレータを定義することができます。

00:08:57.920 --> 00:08:59.560 align:middle
それを見てみましょう。

00:08:59.720 --> 00:09:02.960 align:middle
とりあえず
既に知っているイテレータから出発します。

00:09:03.120 --> 00:09:05.840 align:middle
do: はどうやって実装されているでしょうか？

00:09:06.000 --> 00:09:08.600 align:middle
コレクションの階層で見てみましょう。

00:09:08.760 --> 00:09:13.760 align:middle
SequenceableCollection に実装されています。

00:09:13.920 --> 00:09:16.680 align:middle
do: メソッドは aBock を引数に取ります。

00:09:16.840 --> 00:09:19.400 align:middle
Collectionで定義されているものを実装しています。

00:09:19.560 --> 00:09:23.320 align:middle
1 to: self size do: [i:| aBlock

00:09:23.480 --> 00:09:26.600 align:middle
引数として渡されたブロックに

00:09:26.760 --> 00:09:29.840 align:middle
i 番目の要素を渡して評価します。

00:09:30.000 --> 00:09:31.160 align:middle
とても簡単です。

00:09:31.960 --> 00:09:37.280 align:middle
見てきた通り、Pharo では
イテレータはとても強力です。

00:09:37.440 --> 00:09:41.880 align:middle
各コレクションがイテレータを
多相的にサポートしています。

00:09:42.040 --> 00:09:45.200 align:middle
プログラマは

00:09:45.360 --> 00:09:48.240 align:middle
コレクションクラスで実装された
イテレータを使うことで

00:09:49.000 --> 00:09:51.720 align:middle
そのコレクションに従って
列挙することができます。

00:09:52.520 --> 00:09:55.200 align:middle
新しいイテレータを定義することができます。
とても面白いです。

00:09:55.360 --> 00:09:58.840 align:middle
コレクションクラスに自分のイテレータを
定義することができます。

00:10:00.480 --> 00:10:04.480 align:middle
デザインパターンでのイテレータパターンを
知っている人には気になるかもしれませんが

00:10:05.160 --> 00:10:10.480 align:middle
開発者はいつ次の要素を取り出すかを
決めることはできません。

00:10:10.640 --> 00:10:14.120 align:middle
コレクションが内部でそれを決めます。

00:10:14.280 --> 00:10:17.160 align:middle
next を直接イテレータに
送るのではありません。

00:10:17.320 --> 00:10:20.920 align:middle
イテレータパターンを知っている人には
違和感があるかもしれません。

00:10:21.520 --> 00:10:25.720 align:middle
イテレータはとても強力です。

00:10:25.880 --> 00:10:28.960 align:middle
プログラマの最高の友達です。

00:10:29.120 --> 00:10:31.120 align:middle
プログラムを書くことを簡単にします。

00:10:31.280 --> 00:10:34.280 align:middle
コードを短く、簡潔に、エレガントに
書くことができます。

00:10:34.440 --> 00:10:37.320 align:middle
コレクションの

00:10:37.960 --> 00:10:40.720 align:middle
データのカプセル化を確保します。

