﻿1
00:00:00,440 --> 00:00:04,440
このセッションでは、イテレータと
コレクションについてお話しします。


2
00:00:04,600 --> 00:00:09,000
Pharo でイテレータによって
コレクションの中を列挙する方法を見てみましょう。

3
00:00:09,160 --> 00:00:13,000
Pharo のイテレータの力がわかるでしょう。

4
00:00:13,160 --> 00:00:17,640
よく使う主なイテレータを見てみましょう。

5
00:00:17,800 --> 00:00:19,360
最初の例です。

6
00:00:19,520 --> 00:00:22,680
これは Java で書いた

7
00:00:23,880 --> 00:00:25,320
コレクションを列挙するコードです。

8
00:00:25,480 --> 00:00:28,160
コレクション persons を列挙して

9
00:00:28,320 --> 00:00:31,920
名簿を抽出します。

10
00:00:32,480 --> 00:00:35,240
Pharo ではこのコードを書きます。

11
00:00:35,400 --> 00:00:39,880
collect: イテレータを使います。
これについては後でお話しします。

12
00:00:40,040 --> 00:00:43,360
人々の全ての名前を集めます。

13
00:00:43,520 --> 00:00:47,920
ところで、Java の最新版の Java 8 では

14
00:00:48,080 --> 00:00:51,120
レキシカルクロージャを導入しました。

15
00:00:51,280 --> 00:00:53,640
ブロックと等価なものです。

16
00:00:53,800 --> 00:00:57,000
その結果、構文が Pharo に近付きました。

17
00:00:57,160 --> 00:01:00,200
しかし、Pharo では
最初からブロックがありました。

18
00:01:00,360 --> 00:01:02,440
ブロックはこの言語の心臓部です。

19
00:01:02,600 --> 00:01:07,320
プログラマにとても大きな表現力を
与えます。

20
00:01:08,200 --> 00:01:11,320
とても多くのイテレータがあります。

21
00:01:11,480 --> 00:01:16,400
まず collect: があります。コレクションに
collect: を送ることで何ができるでしょうか？

22
00:01:16,560 --> 00:01:20,240
これは正や負の数のコレクションです。

23
00:01:20,400 --> 00:01:23,200
collect: メッセージを送って
ブロックを渡します。

24
00:01:23,360 --> 00:01:25,560
コレクションを列挙する時は

25
00:01:25,720 --> 00:01:30,160
順番にブロックの引数になります。
2, -3, 4, …という具合に。

26
00:01:30,320 --> 00:01:33,760
そして abs メッセージを送って
絶対値を求めます。

27
00:01:33,920 --> 00:01:36,840
abs メッセージはこの数の絶対値が
欲しいという意味です。

28
00:01:37,000 --> 00:01:40,720
コレクションのそれぞれの要素に対して
ブロックを適用したら

29
00:01:40,880 --> 00:01:43,360
結果が新しいコレクションに集約されます。

30
00:01:43,520 --> 00:01:46,520
collect: に返される結果は
新しいコレクションです。

31
00:01:46,680 --> 00:01:50,160
ブロックがコレクションの各要素に
適用されています。

32
00:01:50,320 --> 00:01:53,800
2 の絶対値
-3 の絶対値つまり 3

33
00:01:53,960 --> 00:01:58,480
4 の絶対値の 4
-35 の絶対値の 35

34
00:01:58,640 --> 00:02:00,320
そして 4 の絶対値の 4

35
00:02:01,080 --> 00:02:04,200
覚えておいておくべきことは

36
00:02:04,360 --> 00:02:06,760
オブジェクトで考えるということです。

37
00:02:06,920 --> 00:02:09,720
コレクションに何かをするようにお願いします。

38
00:02:09,880 --> 00:02:14,440
コレクションは自分で
その要素を列挙します。

39
00:02:14,600 --> 00:02:17,240
各要素への処理を与えます。

40
00:02:17,400 --> 00:02:20,400
これがイテレータの大事な部分です。

41
00:02:21,040 --> 00:02:23,280
これは collect: の別の例です。

42
00:02:23,440 --> 00:02:27,000
このコレクションに
collect: メッセージを送ります。

43
00:02:27,160 --> 00:02:31,000
ブロックでは毎回

44
00:02:31,760 --> 00:02:34,200
要素が奇数か尋ねます。

45
00:02:34,360 --> 00:02:37,160
その結果を全て集約します。

46
00:02:37,320 --> 00:02:40,080
false、true、false、true、と。

47
00:02:43,720 --> 00:02:47,480
もちろん

48
00:02:47,640 --> 00:02:50,400
他の言語でやるように

49
00:02:50,560 --> 00:02:52,680
ブロックやイテレータを使わずに
書くこともできます。

50
00:02:52,840 --> 00:02:55,160
コレクションがあり

51
00:02:55,760 --> 00:02:58,680
結果のコレクションを作り

52
00:02:59,320 --> 00:03:03,560
1 から コレクションの大きさまで
整数を列挙します。

53
00:03:03,720 --> 00:03:04,960
to:do: を使います。

54
00:03:05,120 --> 00:03:08,920
コレクションを列挙して
result コレクションに追加していきます。

55
00:03:09,080 --> 00:03:12,400
こうやって書くこともできます。
全く同じことです。

56
00:03:12,560 --> 00:03:15,440
あなた次第です。
シンプルに書きたいのか

57
00:03:15,600 --> 00:03:19,000
それとも、ややこしく書きたいか。
それだけの話です。

58
00:03:19,160 --> 00:03:22,000
私はシンプルなやり方のほうが断然良いです。

59
00:03:24,200 --> 00:03:27,120
Pharo のコレクションの階層では

60
00:03:28,320 --> 00:03:32,000
全てのコレクションは多相的で

61
00:03:32,160 --> 00:03:35,080
Collectionクラスを継承しています。
つまり、共通の API があります。

62
00:03:35,240 --> 00:03:39,720
長所として、大部分のコレクションで

63
00:03:39,880 --> 00:03:42,840
同じイテレータを使えます。

64
00:03:44,480 --> 00:03:48,080
それがオブジェクトで考えるということです。

65
00:03:48,240 --> 00:03:51,280
コレクションに
自分の中身を列挙するように言います。

66
00:03:51,440 --> 00:03:54,800
言った側は Dictionary（辞書）を
使っているのかどうかも、わかりません。

67
00:03:54,960 --> 00:03:58,880
我々はキーや値がどうしたという
内部的なロジックを知りたくはありません。

68
00:03:59,400 --> 00:04:02,320
だからコレクションに行儀よくお願いして

69
00:04:02,480 --> 00:04:04,960
その要素を処理してもらうのです。

70
00:04:06,640 --> 00:04:11,320
沢山のイテレータが使えます。
do: と collect: はもう見ましたね。

71
00:04:11,480 --> 00:04:14,280
他にももっとあります。
select:、 reject:、 detect:、などなど。

72
00:04:14,440 --> 00:04:17,840
このコースではそのうちいくつかを
後で学びます。

73
00:04:19,320 --> 00:04:22,760
do: は最も単純なイテレータです。

74
00:04:22,920 --> 00:04:26,960
do: はコレクションの各要素を列挙します。
トランスクリプトに表示します。

75
00:04:27,120 --> 00:04:30,560
もう何度も勉強しましたね。

76
00:04:30,720 --> 00:04:33,320
新しいイテレータがあります。select: です。

77
00:04:33,480 --> 00:04:36,560
コレクションの要素のうち

78
00:04:36,720 --> 00:04:38,360
条件に合ったもの全てを得ます。

79
00:04:38,520 --> 00:04:41,960
コレクションの要素のうち
奇数のものを得ます。

80
00:04:42,120 --> 00:04:45,040
このコレクションに select: を送ります。

81
00:04:45,200 --> 00:04:46,440
ブロックを渡します。

82
00:04:46,600 --> 00:04:49,560
ブロックの値が true であれば

83
00:04:49,720 --> 00:04:53,080
その要素は結果のコレクションに追加されます。

84
00:04:55,040 --> 00:04:58,080
select: #odd と全く同じです。

85
00:04:58,240 --> 00:05:01,120
ブロックの中で

86
00:05:01,280 --> 00:05:05,400
ブロックの引数に単項メッセージを

87
00:05:05,560 --> 00:05:06,920
送っているだけであれば

88
00:05:07,080 --> 00:05:10,760
メッセージの名前をシンボルとして
渡すことができます。

89
00:05:10,920 --> 00:05:12,480
このほうが、より短く書けます。

90
00:05:12,640 --> 00:05:16,000
単項メッセージしか使えません。

91
00:05:17,920 --> 00:05:20,880
他のイテレータとしては reject: があります。

92
00:05:21,040 --> 00:05:24,160
このコレクションの要素のうち
奇数のものを取り除いたものを得ます。

93
00:05:24,320 --> 00:05:27,520
結果として偶数のみが残っています。

94
00:05:28,520 --> 00:05:30,160
また、detect: もあります。

95
00:05:30,320 --> 00:05:34,000
条件に合う最初の要素を見つけます。

96
00:05:34,160 --> 00:05:37,000
つまりブロックの値が true になるものです。

97
00:05:37,160 --> 00:05:40,920
このコレクションの最初の奇数要素を得ます。
11 です。

98
00:05:42,320 --> 00:05:46,880
条件に合う最初の要素が欲しいわけですが

99
00:05:47,040 --> 00:05:50,120
条件に合うものが 1 つもない場合には
デフォルトが欲しくなります。

100
00:05:50,280 --> 00:05:52,440
detect:ifNone: です。

101
00:05:52,600 --> 00:05:57,360
もし条件に合うものがなければ
このブロックの値を返します。

102
00:05:57,520 --> 00:05:59,640
この場合、0 です。

103
00:05:59,800 --> 00:06:04,800
他にもプログラマを楽にしてくれる
イテレータがあります。

104
00:06:04,960 --> 00:06:06,800
例えば、anySatisfy: です。

105
00:06:06,960 --> 00:06:10,600
条件に合う要素が 1 つでもあるか確認します。

106
00:06:10,760 --> 00:06:13,320
全ての要素が条件に合うか確認する
ことができます。

107
00:06:13,480 --> 00:06:17,320
末尾から逆順にコレクションを列挙する
ことができます。

108
00:06:17,480 --> 00:06:22,360
コレクションのインデックスと要素を列挙したり
要素を2つずつ列挙することもできます。

109
00:06:22,520 --> 00:06:26,480
要素から全ての順列を列挙することができます。

110
00:06:26,640 --> 00:06:28,960
沢山のイテレータがあります。

111
00:06:29,120 --> 00:06:31,480
新しいイテレータを作ることもできます。

112
00:06:31,640 --> 00:06:35,320
コレクション 1 2 3 を

113
00:06:35,480 --> 00:06:38,440
もう 1 つのコレクションと一緒に
列挙します。

114
00:06:38,600 --> 00:06:42,600
do: の引数のブロックには
:x と :y の 2 つの引数があります。

115
00:06:42,760 --> 00:06:46,840
:x は1つ目のコレクションの要素

116
00:06:47,000 --> 00:06:48,920
:y は2つ目のコレクションの要素です。

117
00:06:49,080 --> 00:06:51,080
これらの要素を掛け算します。

118
00:06:51,240 --> 00:06:53,720
結果は 10、40、90 です。

119
00:06:54,840 --> 00:06:59,440
もちろん、このイテレータを使うには
コレクションの長さが同じでなければなりません。

120
00:07:01,360 --> 00:07:04,720
他にもあります。

121
00:07:04,880 --> 00:07:08,120
ここでは do:separatedBy: を使っています。

122
00:07:08,280 --> 00:07:11,280
コレクションの各要素を列挙しますが

123
00:07:11,440 --> 00:07:14,040
1つの要素を挙げる毎に

124
00:07:14,200 --> 00:07:17,680
コンマを書き出すブロックを評価します。

125
00:07:17,840 --> 00:07:20,480
つまり、a を挙げて

126
00:07:20,640 --> 00:07:23,320
コンマを表示して、次に b で
次にコンマ、次に c となります。

127
00:07:23,480 --> 00:07:26,400
各要素の間に
1つのアクションを実行します。

128
00:07:28,880 --> 00:07:31,640
これは groupBy: イテレータです。

129
00:07:31,800 --> 00:07:36,040
コレクションの要素を条件に従って

130
00:07:36,200 --> 00:07:37,720
グループ分けします。

131
00:07:37,880 --> 00:07:42,040
コレクション 1 2 3 4 5 6 7 に
このメッセージを送ります。

132
00:07:42,200 --> 00:07:45,480
結果として辞書が得られます。

133
00:07:47,000 --> 00:07:50,440
この #even という条件に対して

134
00:07:50,600 --> 00:07:52,800
false だった全ての要素がこれです。

135
00:07:52,960 --> 00:07:56,000
見ての通り
奇数の要素全てです。

136
00:07:56,160 --> 00:07:59,520
偶数の要素はすべて true を返します。

137
00:08:02,280 --> 00:08:04,520
よくあることですが

138
00:08:04,680 --> 00:08:07,720
コレクションの中にコレクションを
入れ子にしがちです。

139
00:08:07,880 --> 00:08:11,440
結果として深いレベルの入れ子になります。

140
00:08:11,600 --> 00:08:14,480
これは手で作った例ですが

141
00:08:14,640 --> 00:08:17,560
コレクションの中にコレクションが
入れ子になっています。

142
00:08:17,720 --> 00:08:22,200
このコレクションをフラットにします。
それぞれの要素を引っ張り出して。

143
00:08:22,880 --> 00:08:26,960
Pharo では簡単な方法があります。

144
00:08:27,120 --> 00:08:29,120
flatCollect: イテレータです。

145
00:08:29,280 --> 00:08:33,520
要素を列挙して
新しい平坦なコレクションを作ります。

146
00:08:35,240 --> 00:08:38,280
コレクション 1 2 3 4 5 6 が得られます。

147
00:08:38,440 --> 00:08:40,600
入れ子は無くなっています。

148
00:08:44,040 --> 00:08:48,520
Pharo の全てのイテレータについて
説明するつもりはありません。

149
00:08:48,680 --> 00:08:52,480
そんなことしたらダラダラと退屈なことになります。
ただ、沢山あるということはお見せしたいと思います。

150
00:08:52,640 --> 00:08:54,280
コレクションのクラスを読んで

151
00:08:54,440 --> 00:08:57,760
自分でイテレータを定義することができます。

152
00:08:57,920 --> 00:08:59,560
それを見てみましょう。

153
00:08:59,720 --> 00:09:02,960
とりあえず
既に知っているイテレータから出発します。

154
00:09:03,120 --> 00:09:05,840
do: はどうやって実装されているでしょうか？

155
00:09:06,000 --> 00:09:08,600
コレクションの階層で見てみましょう。

156
00:09:08,760 --> 00:09:13,760
SequenceableCollection に実装されています。

157
00:09:13,920 --> 00:09:16,680
do: メソッドは aBock を引数に取ります。

158
00:09:16,840 --> 00:09:19,400
Collectionで定義されているものを実装しています。

159
00:09:19,560 --> 00:09:23,320
1 to: self size do: [i:| aBlock

160
00:09:23,480 --> 00:09:26,600
引数として渡されたブロックに

161
00:09:26,760 --> 00:09:29,840
i 番目の要素を渡して評価します。

162
00:09:30,000 --> 00:09:31,160
とても簡単です。

163
00:09:31,960 --> 00:09:37,280
見てきた通り、Pharo では
イテレータはとても強力です。

164
00:09:37,440 --> 00:09:41,880
各コレクションがイテレータを
多相的にサポートしています。

165
00:09:42,040 --> 00:09:45,200
プログラマは

166
00:09:45,360 --> 00:09:48,240
コレクションクラスで実装された
イテレータを使うことで

167
00:09:49,000 --> 00:09:51,720
そのコレクションに従って
列挙することができます。

168
00:09:52,520 --> 00:09:55,200
新しいイテレータを定義することができます。
とても面白いです。

169
00:09:55,360 --> 00:09:58,840
コレクションクラスに自分のイテレータを
定義することができます。

170
00:10:00,480 --> 00:10:04,480
デザインパターンでのイテレータパターンを
知っている人には気になるかもしれませんが

171
00:10:05,160 --> 00:10:10,480
開発者はいつ次の要素を取り出すかを
決めることはできません。

172
00:10:10,640 --> 00:10:14,120
コレクションが内部でそれを決めます。

173
00:10:14,280 --> 00:10:17,160
next を直接イテレータに
送るのではありません。

174
00:10:17,320 --> 00:10:20,920
イテレータパターンを知っている人には
違和感があるかもしれません。

175
00:10:21,520 --> 00:10:25,720
イテレータはとても強力です。

176
00:10:25,880 --> 00:10:28,960
プログラマの最高の友達です。

177
00:10:29,120 --> 00:10:31,120
プログラムを書くことを簡単にします。

178
00:10:31,280 --> 00:10:34,280
コードを短く、簡潔に、エレガントに
書くことができます。

179
00:10:34,440 --> 00:10:37,320
コレクションの

180
00:10:37,960 --> 00:10:40,720
データのカプセル化を確保します。
