vieweditattachhistorytopchangessearchhelp

第38回


■SqueakではじめるSmalltalk入門   第38回


 本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。Smalltalkプログラミングには欠かせないコレクション。このコレクションの抽象クラス「Collection」のプロトコルである、accessing、adapting、adding、arithmetic、enumerating、converting、それぞれに属するメソッドを起動するためのメッセージが送信されたとき、コレクションがどんな振る舞いをするのかをこれまで見てきました。今回は残りのmath functions、removing、testingの各プロトコルを取りあげます。

 math functionsプロトコルには、単項メッセージで起動され、そのとき代数的関数のような役割りを果たすメソッドがまとめられています。

#(1 2 3 4) sum      " => 10 " "合計を求める"
#(1 2 3 4) min      " => 1  " "最小値      "
#(1 2 3 4) max      " => 4  " "最大値      "
#(1 2 3 4) negated  " => #(-1 -2 -3 -4) " "各要素の符号反転"


 Collectionのmath functionプロトコルを閲覧している状態で、ブラウザ上段右端のペインから各メソッド名(セレクタ)をクリックすると、対応するメソッドの定義が下のコードペインに表示されます。このプロトコルに属するメソッドは、#sumや#max、#minのように結果を求めるために特殊な手続きが必要なタイプのものと、#negatedのように#collect:を使って、各要素に単純にメッセージを送り直した結果を新しいコレクションとして返すタイプのものに大別できます。

Collection >> max
   ^ self inject: self anyOne into: [:max :each | max max: each]

Collection >> negated
   ^ self collect: [:a | a negated]


 ちなみにanyOneは、レシーバの適当な(実際には最初の)要素を返すメソッドを起動するメッセージです。

 arithmeticプロトコルに属するメソッド同様、math functionsに属するメソッドも、起動時のコンテキストにおいてレシーバのすべての要素が数値かそれに準ずるものであることが期待されます。

#(1 #two 3 4) negated  " => error "


 removingプロトコルには、レシーバから要素を取り除くためのメソッドが属します。基本的なメソッドは、#remove:、#remove:ifAbsent:、#removeAll:です。addingプロトコルのメソッド同様、removingプロトコルのメソッドも削除した要素を返値とする慣習があるので、ここでは便宜的にレシーバを返すyourselfというメッセージを送っています。

#(1 2 2 3 3 3) asSet remove: 2; yourself   " => a Set(1 3) "
#(1 2 2 3 3 3) asSet remove: 4  " => Error: Object is not in the collection. "
#(1 2 2 3 3 3) asSet remove: 4 ifAbsent: []; yourself  " => a Set(1 2 3) "
#(1 2 2 3 3 3) asSet removeAll: #(1 2); yourself  " => a Set(3) "


 メッセージ「remove: oldElement」は、レシーバからoldElementを削除します。もちろん、要素の増減が可能なコレクションに限ります。

#(1 2 3) remove: 2
   " => Error: This message is not appropriate for this object "


 取り除こうとする要素がレシーバに含まれているかどうかわからないときは、メッセージ「remove: oldElement ifAbsent: [...]」を送ります。第二パラメータのブロックには、削除したい要素がレシーバに見つからないときの処理を記述します。何もしないときは上述のように空のブロック「[]」を渡しておけばよいでしょう。

 メッセージ「removeAll: aCollection」は、aCollectionに含まれる要素をすべてレシーバから削除します。これは、aCollectionに対する要素の列挙と、#remove:を使って表現できそうですね。実際に#removeAll:を見てみると、たしかにその通りの定義になっています。

Collection >> removeAll: aCollection
   aCollection do: [:each | self remove: each].
   ^ aCollection


 コレクションのプロトコル探索の最後はtestingです。ここで注目するメソッドは、#includes:、#isEmpty、#occurrencesOf:です。

#(1 2 2 3 3 3) includes: 2       " => true  "
#(1 2 2 3 3 3) includes: 4       " => false "
'squeak' includes: $a            " => true  "
'squeak' includes: $x            " => false "
#(1 2 2 3 3 3) isEmpty           " => false "
#() isEmpty                      " => true  "
'squeak' isEmpty                 " => false "
'' isEmpty                       " => true  "
#(1 2 2 3 3 3) occurrencesOf: 4  " => 0     "
'SMALLTALK' occurrencesOf: $L    " => 3     "


 「includes: anObject」はレシーバがanObjectを含むかどうかを真偽値で返させます。isEmptyは、単純にレシーバが空(カラ)つまり要素を持たないか否かを、やはり真偽値で返させます。

 isEmptyの逆、つまり、要素を有するか否かを聞きたいときは、isEmptyの返値にnotを送信して反転させる…という手の他に、notEmptyというメッセージを送る方法もあります。

#(1 2 2 3 3 3) isEmpty not   " => true "
#(1 2 2 3 3 3) notEmpty      " => true "


 メッセージ「occurrencesOf: anObject」は、anObjectのレシーバ内での出現回数を尋ねるときに送ります。

 以上、駆け足でしたが、Smalltalkのコレクションが共通して受け付けるメッセージと、そのときに期待される振る舞いについての簡単な解説を終わります。

このページを編集 (4608 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 773 times.