Зачем использовать оператор обратной трубы вместо цепочки функций? - PullRequest
29 голосов
/ 26 марта 2011

Зачем использовать оператор обратной трубы вместо цепочки функций?

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 ]

33 голосов
/ 26 марта 2011

Из-за левой ассоциативности (f <| g <| x анализируется как (f <| g) <| x и, к сожалению, не как f <| (g <| x), что эквивалентно x |> g |> f), я нашел это полезным, только если вы хотите удалить скобки (вместо f (long expression), вы пишете f <| long expression).

20 голосов
/ 26 марта 2011

Выбор между 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 #.Благодаря оператору <| вам не нужны завершающие скобки.

6 голосов
/ 19 января 2016

Как Скотт Влашин указал здесь , оператор обратной трубы полезен , если вам необходимо передать данные в качестве первого параметра (а не последнего) где-то вдоль цепочки каналов . Учтите следующее:

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 - это "дерьмовый день рождения", чего я и хочу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...