タプルは、名前を持たないけれど順序のある値をまとめた、_不変_のグループです。 タプルには、どんなデータ型でも(複数でも)入れることができます。別のタプルを入れることもできます。
タプルは、(と)の文字の間にカンマで区切った値を並べて定義します:(<element_1>, ... , <element_n>)。
("one", 2) // Tuple pair (2 values)
("one", 2, true) // Tuple triplet (3 values)
比較できるのは、同じ長さで同じ型を(同じ順序で)持つタプル同士だけです。 タプルは構造的等価性を持ちます。つまり、すべての値が等しいときに_だけ_、2つのタプルは等しいとみなされます。
(1, 2) = (1, 2) // Same length, same types, same values, same order
// => true
(1, 2) = (2, 1) // Same length, same types, same values, different order
// => false
(1, 2) = (1, "2") // Same length, different types
// compiler error
(1, 2) = (1, 2, 3) // Different length
// compiler error
タプルから値を取り出す方法は、次の3つです:
fstとsndの関数let person = ("Jordan", 170)
// Option 1: fst/snd
let name1 = fst person
let length2 = snd person
// Option 2: deconstruction
let (name2, length2) = person
// => name2 = "Jordan"
// => length2 = 170
// Option 3: pattern matching
match person with
| name3, length3 -> printf "%s: %d" name3 length3
AzaraとRuiは、海賊をテーマにした宝探しで競い合うチームメイトです。 片方は宝の名前と地図上の座標のリストを、もう片方は場所の名前と地図上の座標のリストを持っています。 二人には、出発地点にYOU ARE HEREと記された白地図も渡されています。
| Azaraのリスト | Ruiのリスト | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
でも、少し整理されていません。Azaraの座標は、Ruiのものとは形式も並び順も違うようで、どの宝がどの場所に対応するのかを知るには、二つのリストを何度も見比べなければなりません。 そこで、F#を学び始めたばかりの二人が、宝探しの情報をうまく整理するために、小さなプログラム(というより、いくつかの関数)を書くのを手伝ってほしいと頼みに来ました。
Azaraのリストから(treasure, coordinate)のペアを受け取り、抽出した地図上の座標だけを返すgetCooordinate()関数を実装しましょう。
getCoordinate ("Scrimshaw Whale's Tooth", "2A")
// "2A"
"2A"という形式の座標を受け取り、(2, 'A')という形式のタプルを返すconvertCoordinate()関数を実装しましょう。
convertCoordinate "2A"
// (2, 'A')
(treasure, coordinate)のペアと、(location, coordinate, quadrant)のレコードを受け取り、それぞれの座標を比較するcompareRecords()関数を実装しましょう。
座標が「一致」すれば**trueを返し、一致しなければfalse**を返します。
正確に比較できるように、必要に応じて座標の形式を整えましょう。
compareRecords ("Brass Spyglass", "4B") ("Seaside Cottages", (1, 'C'), "blue")
// false
compareRecords ("Model Ship in Large Bottle", "8A") ("Harbor Managers Office", (8, 'A'), "purple")
// true
Azaraのリストの(treasure, coordinate)のペアと、Ruiのリストの(location, coordinate, quadrant)のレコードを受け取り、座標が一致すれば(coordinate, location, quadrant, treasure)を返すcreaterecord()関数を実装しましょう。
座標が_一致しなければ_、同じ形で""で埋めたタプルを返します。
正確に比較できるように、必要に応じて座標の形式を整えましょう。
createRecord ("Brass Spyglass", "4B") ("Abandoned Lighthouse", (4, 'B'), "Blue")
// ("4B", "Abandoned Lighthouse", "Blue", "Brass Spyglass")
createRecord ("Brass Spyglass", "4B") ("Seaside Cottages", (1, 'C'), "Blue")
// ("", "", "", "")