コレクションの反復処理
コレクションを使った反復処理を説明します。コレクションは同じ型の値をもった集合体ですから、反復処理を行うのに適しています。全要素について反復処理を行うには、for文を使います。
最初の構文は、コレクションの要素の値を順番に取り出し、処理を繰り返します。Array-of、HashTable-of、Set-of すべてで利用できます。
{for 要素変数:型 in コレクション変数 do
処理
}
整数配列に初期値を設定して、全要素の合計値を求めるサンプルです。
{curl 7.0 applet}
{curl-file-attributes character-encoding = "shift-jis"}
{value
def array = {{Array-of int} 11, 13, 15, 17, 19, 21}
let sum:int = 0
{for element:int in array do
{inc sum, element}
}
sum
}
実行結果は、96 です。
次の構文は、コレクションの要素のキーを取り出し、処理を繰り返します。Array-of の場合は、キーはインデックス番号になります。HashTable-of の場合は、キーの値です。Set-of ではキーがないので利用できません。
{for key キー変数:型 in コレクション変数 do
処理
}
キーを文字列、値を整数のハッシュテーブルで、要素のキーの平均文字列長を出すサンプルです。
{curl 7.0 applet}
{curl-file-attributes character-encoding = "shift-jis"}
{value
def map = {{HashTable-of String, int}}
{map.set "zero", 0}
{map.set "one", 1}
{map.set "two", 2}
{map.set "tree", 3}
let sum:int = 0
{for key element:String in map do
{inc sum, element.size}
}
sum / map.size
}
実行結果は、3.5 です。
最後の構文は、コレクションの要素のキーと値の両方を取り出し、処理を繰り返します。Array-of の場合は、キーはインデックス番号、値は要素になります。HashTable-of の場合は、キーの値と要素の値です。Set-of ではキーがないので利用できません。
{for 要素変数:型 key キー変数:型 in コレクション変数 do
処理
}
キー、値がそれぞれ整数のハッシュテーブルで、キーと値の両方の合計値を出すサンプルです。
{curl 7.0 applet}
{curl-file-attributes character-encoding = "shift-jis"}
{value
def map = {{HashTable-of int, int}}
{map.set 11, 40}
{map.set 12, 17}
{map.set 15, 22}
{map.set 32, 34}
let sum-key:int = 0
let sum-val:int = 0
{for value:int key key-value:int in map do
{inc sum-key, key-value}
{inc sum-val, value}
}
{format "key:%d / value:%d", sum-key, sum-val}
}
実行結果は、key:70 / value:113 です。
独自クラスをキーに利用する
セットやハッシュテーブルはキー項目にどのような型でも指定できます。しかし、キーがユニークであるか否かの判定は、== 演算子、つまりインスタンスの一致がデフォルトの動作になります。
==演算子の処理では具合が悪い場合には、コレクションにインスタンスの同一を判定するプロシージャおよびハッシュ値の計算を行うプロシージャを指定する事で任意の一致条件を利用できます。セットでもハッシュテーブルでも指定方法は同じです。
少々長いのですが、以下にサンプルコードを示します。まず、Pointクラスを定義しています。Pointクラスは、x、y の2つのdoubleの値を持っているので、2つのインスタンスの一致条件をx、yの両方の値が等しいことにしています。また、ハッシュ値の生成は、2つの値を単純に合計してCurlのデフォルトのハッシュ計算用プロシージャ value-hash に渡しています。
{curl 7.0 applet}
{curl-file-attributes character-encoding = "shift-jis"}
|| 独自クラスを定義
{define-class public Point
|| デフォルトコンストラクタ
{constructor public {default x:double, y:double}
set self.x = x
set self.y = y
}
|| x座標
field public x:double
|| y座標
field public y:double
|| 原点からの距離
{method public {get-distance}:double
{return {sqrt {pow self.x, 2} + {pow self.y ,2}}}
}
}
{value
def set0 = {{Set-of Point}}
def v-hash = {proc {point:Point}:int
{return {value-hash point.x + point.y}}
}
def equals? = {proc {p0:Point, p1:Point}:bool
{return p0.x == p1.x and p0.y == p1.y}
}
def set1 = {{Set-of Point,
key-hash-proc = v-hash,
key-equality-proc = equals?}
}
{set0.insert {Point 10.0, 20.0}}
{set1.insert {Point 10.0, 20.0}}
def result0 = {set0.member? {Point 10.0, 20.0}}
def result1 = {set1.member? {Point 10.0, 20.0}}
{format "==判定では %s、proc判定では %s", result0, result1}
}
実行結果は、==判定では false、proc判定では true となります。
最後に
Curl言語のコレクションについて見てきました。パラメータ化クラスによって実装されており、キーの一致条件なども任意に設定できるなど十分な汎用性を持っています。Java等では、クラスごとのequalsメソッドで一致条件を定義するのに対し、Curl言語ではオブジェクトを格納するコレクション側で一致条件を指定できるため、より柔軟な処理が可能になります。
Curl言語に標準で実装されているコレクションの他に、順番を保持したHashTableやSetなどが、Curl拡張ライブラリとしてオープンソースで提供されています。カールデベロッパーセンターにアクセスしてみてください。


