Конвейер |> и композиция >>
Два оператора, формирующие стиль F#: конвейер |> для данных и композиция >> для функций.
Оператор конвейера
|>передаёт значение слева как последний аргумент функции справа:x |> fравноf x.
Зачем конвейер
Без конвейера вложенные вызовы читаются «изнутри наружу»: List.sum (List.map square (List.filter even xs)). Это тяжело читать. Конвейер разворачивает поток данных слева направо, как мы и думаем о преобразованиях.
let xs = [1; 2; 3; 4; 5; 6]
let result =
xs
|> List.filter (fun n -> n % 2 = 0)
|> List.map (fun n -> n * n)
|> List.sum
printfn "%d" resultВывод:
56
Читается как рассказ: взять xs, отфильтровать чётные ([2;4;6]), возвести в квадрат ([4;16;36]), сложить (56). Каждый шаг получает результат предыдущего.
Почему именно «последний аргумент»
Функции коллекций в F# спроектированы так, что обрабатываемые данные — последний параметр (List.map f список). А |> подставляет значение именно последним. В сочетании с частичным применением (List.map square — это функция от списка) конвейер складывается идеально.
Композиция функций >>
Оператор >> склеивает две функции в одну: (f >> g) x равно g (f x) — сначала f, потом g. Разница с конвейером: |> работает со значениями, >> — с функциями, создавая новую функцию без упоминания аргумента.
let addOne x = x + 1
let double x = x * 2
let addThenDouble = addOne >> double // сначала +1, потом *2
printfn "%d" (addThenDouble 5)Вывод:
12
5 + 1 = 6, затем 6 * 2 = 12. Получилась новая функция addThenDouble без явного аргумента — это называют «point-free» стилем.
Обратные операторы
Есть и зеркальные версии: <| (обратный конвейер, f <| x = f x, иногда экономит скобки) и << (обратная композиция, g << f = сначала f). Используются реже; основной рабочий инструмент — |>.
Как работает под капотом
Оба оператора — это обычные функции из стандартной библиотеки, определённые элементарно: let (|>) x f = f x и let (>>) f g x = g (f x). Никакой магии компилятора — это просто инфиксные функции. Поэтому их можно переопределять и понимать как обычный код. Компилятор инлайнит их, так что накладных расходов в рантайме нет.
Частые ошибки
- Путать
|>(значение в функцию) и>>(функция в функцию). - Думать, что
>>применяет функции справа налево — нет,f >> g— сначалаf. - Переусердствовать с point-free стилем — иногда явный аргумент читается понятнее.
Итоги
x |> f=f x— конвейер выстраивает поток данных слева направо.- Функции коллекций берут данные последним аргументом — это и делает
|>удобным. f >> g= сначалаf, потомg— композиция создаёт новую функцию.- Оба оператора — обычные функции стандартной библиотеки, без магии.