Зачем использовать оператор обратной трубы вместо цепочки функций?
Зачем использовать оператор обратной трубы вместо цепочки функций?
let distanceFromOrigin aPoint =
let square x = x * x
sqrt (square aPoint.x + square aPoint.y)
против
let distanceFromOrigin aPoint =
let square x = x * x
sqrt <| square aPoint.x + square aPoint.y
3 ответа
Из-за левой ассоциативности (f <| g <| x
анализируется как (f <| g) <| x
и, к сожалению, не так f <| (g <| x)
что эквивалентно x |> g |> f
), Я нашел это полезным только тогда, когда вы хотите удалить скобки (вместо f (long expression)
, ты пишешь f <| long expression
).
Выбор между f x
, x |> f
а также f <| x
это в основном вопрос стиля. Там нет абсолютного правила для выбора одного вместо другого. |>
Оператор очень популярен, и его стоит использовать.
<|
встречается реже, но если вы заглянете в исходники компилятора, вы найдете несколько вариантов использования. Например:
raise <| System.InvalidOperationException (SR.GetString(SR.QillFormedAppOrLet))
if info.precision then
failwithf "%s" <| FSComp.SR.forFormatDoesntSupportPrecision(ch.ToString())
<|
используется для удаления скобок, и я думаю, что это делает код более читабельным при аккуратном использовании. Когда вы видите это, вы знаете, что следующее выражение является аргументом вашей функции. Вам не нужно искать закрывающую скобку. Я предлагаю вам использовать его экономно, и вы должны вообще избегать смешивания <|
а также |>
в том же выражении, поскольку это может быть очень запутанным.
Мне иногда нравится использовать этот оператор для создания "блока", сfun
или же lazy
ключевое слово.
let f (l: Lazy<_>) = ()
let g (f: _ -> _ -> _) = ()
f <| lazy
let x = 1 + 1
x * x
g <| fun x y ->
let sqr n = n * n
sqr x + sqr y
Блок основан на отступе, поэтому он хорошо вписывается в код F#. Благодаря <|
Оператор, вам не нужны завершающие скобки.
Как указал здесь Скотт Влашин, оператор обратного канала полезен, если вам нужно передать данные в качестве первого параметра (а не последнего) где-то вдоль цепочки каналов. Учтите следующее:
let replace (replaceThis: string) (withThis: string) (input: string) =
input.Replace(replaceThis, withThis)
let joinWith (input1: string) (input2: string) =
input1 + " " + input2
let testString = "Happy"
let amendedString = testString
|> replace "H" "Cr"
|> joinWith "birthday"
amendedString
это "день рождения дерьмовый". Допустим, я хочу, чтобы это был "Сумасшедший день рождения". Я могу добиться этого с помощью оператора обратной трубы:
let amendedString = testString
|> replace "H" "Cr"
|> joinWith <| "birthday"
Сейчас amendedString
это "дерьмовый день рождения", что я и хочу.