Кортеж (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.