Подтвердить что ты не робот

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

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

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
4b9b3361

Ответ 1

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

Ответ 2

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

Ответ 3

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

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 - это день рождения Crappy. Скажем, я хочу, чтобы это было "Crappy birthday". Я могу добиться этого, используя оператор обратной трубы:

let amendedString = testString
                    |> replace "H" "Cr"
                    |> joinWith <| "birthday"

Теперь amendedString - это "Crappy birthday", который я хочу.