Кортеж (tuple) представляет набор упорядоченных значений, которые могут представлять различные типы.
Для определения кортежа набор значений заключатся в скобки и оделяется друг от друга запятой:
let user = ("Tom", 37)
В примере выше кортеж называется user и состоит из двух элементов: строки "Tom" и числа 37.
Как и любые данные, в языке F# кортеж имеет свой тип, который складывается из типа его элементов. И мы можем явным образом указывать тип:
let user: string * int = ("Tom", 37)
Тип string * int указывает, что это кортеж, который состоит из двух элементов. Причем первый элемент должен представлять тип string,
а второй - тип int.
Другой пример:
let person: string * int * float * bool = ("Sam", 25, 1.78, true)
Здесь кортеж должен состоять из четырех компонентов, где третий компонент должен представлять тип float, а четвертый - тип bool.
Кортежи могут представлять как ссылочные типы - классы, так и типы значений - структуры. Создаваемый по умолчанию кортеж представляет ссылочный тип или класс. Например:
let user = ("Tom", 37)
Здесь кортеж user является ссылочным.
Для создания кортежа-структуры его определение предваряется оператором struct:
let person = struct("Sam", 25)
Если нам надо также указать тип для кортежа-структуры, то в определение типа также входит оператор struct:
let person: struct(string * int) = ("Sam", 25)
Причем при присвоении значения можно не указывать оператор struct.
С помощью оператора let можно разложить кортеж на отдельные значения:
let user = ("Tom", 37)
let (name, age) = user
printfn $"Name: {name} Age: {age}" // Name: Tom Age: 37
В данном случае получаем первый компонент кортежа user в значение name, а второй компонент - в значение age.
Если мы хотим получить не все, а только некоторые компоненты кортежа, то для ненужных компонентов нужно указать прочерк:
let user = ("Tom", 37, "Microsoft")
let (name, age, _) = user // получаем первые два компонента кортежа
printfn $"Name: {name} Age: {age}" // Name: Tom Age: 37
let(_, _, company) = user // получаем только третий компонент кортежа
printfn $"Company: {company}" // Company: Microsoft
Кроме того, для ссылочных кортежей доступны две специальные функции: fst (возвращает первый элемент кортежа) и snd (возвращает второй элемент кортежа)
let user = ("Tom", 37)
let name = fst user
let age = snd user
printfn $"Name: {name} Age: {age}" // Name: Tom Age: 37
Следует отметить, что в этом случае кортеж должен иметь только два элемента.
Если производится разложение кортежа-структуры, то перед набором значений указывается оператор struct:
let person: struct(string * int) = ("Sam", 25)
let struct (name, age) = person
Параметр может представлять кортеж. Например:
let user = ("Tom", 37)
let printValues (a, b) = // определение функции
printfn $"a = {a} b = {b}"
printValues user // a = Tom b = 37
Если функция должна принять кортеж в качестве параметра, то параметр определяется с помощью скобок, в которых определяется количество элементов кортежа.
То есть в данном случае (a, b) означает, что это будет кортеж из двух элементов. При чем функция автоматически раскладывает передаваемый кортеж
на значения a и b.
Но, следует отметить, что определение кортежа в качестве параметра следует отличать от простого определения параметров:
let printValues a b = printfn $"a = {a} b = {b}"
Или определения типизированных параметров:
let printValues (a: string, b: int) = printfn $"a = {a} b = {b}"
В обоих случаях выше мы не можем передать в функцию кортеж.
Если же нам надо явным образом указать тип кортежа, то он, как и в общем случае, указывается через двоеточие после параметра, а сам параметр заключается в скобки:
let user = ("Tom", 37)
let printValues ((a, b): string * int) = printfn $"a = {a} b = {b}"
printValues user // a = Tom b = 37
В данном случае значение для параметра должно представлять двухэлементный кортеж, первый элемент которого - строка, а второй - целое число типа int.
Кортеж представляет удобный способ получить из функции несколько значений:
let divRem a b = let x = a / b let y = a % b (x, y) let (quotient, remainder) = divRem 15 6 printfn "Результат: %d" quotient // 2 printfn "Остаток: %d" remainder // 3 (15-2*6)
Здесь функция divRem принимает два параметра - делимое и делитель и возвращает целочисленный результат деления и остаток от деления.
А поскольку функция единовременно может возвратить только одно значение, то объединяем оба значения в кортеж.
Также мы можем явно определить тип возвращаемого кортежа:
let divRem a b : struct(int*int) = let x = a / b let y = a % b struct(x, y) let struct(quotient, remainder) = divRem 15 6 printfn "Результат: %d" quotient // 2 printfn "Остаток: %d" remainder // 3 (15-2*6)
Здесь функция divRem возвращает кортеж-структуру, которая состоит из значений типа int.