为什么使用Backward Pipe Operator而不是Function Chaining?

时间:2011-03-26 16:58:05

标签: f#

为什么使用反向管道运算符而不是函数链?

let distanceFromOrigin aPoint =
    let square x = x * x
    sqrt (square aPoint.x + square aPoint.y)

VS

let distanceFromOrigin aPoint =
    let square x = x * x
    sqrt <| square aPoint.x + square aPoint.y

3 个答案:

答案 0 :(得分:33)

由于左侧关联性(f <| g <| x被解析为(f <| g) <| x而遗憾地不被f <| (g <| x)等同于x |> g |> f),我发现它仅在您需要时才有用要删除括号(而不是f (long expression),请编写f <| long expression)。

答案 1 :(得分:20)

f xx |> ff <| x之间进行选择主要是一个问题 样式。选择一个而不是选择一个没有绝对的规则 其他。 |>运算符非常受欢迎,使用它是个好主意。

<|不太常见,但如果你查看编译器的来源,你会发现几个 使用。例如:

raise <| System.InvalidOperationException (SR.GetString(SR.QillFormedAppOrLet))

if info.precision then
  failwithf "%s" <| FSComp.SR.forFormatDoesntSupportPrecision(ch.ToString())

<|用于删除括号,我认为它会生成代码 仔细使用时更具可读性。当你看到它时,你就知道了 以下表达式是函数的参数。你没有 必须搜索右括号。我建议你谨慎使用它,你通常应该避免在同一个表达式中混合<||>,因为它可能非常 混乱。

我有时喜欢使用此运算符来创建“块” funlazy关键字。

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#代码。谢谢 到<|运算符,您不需要尾随括号。

答案 2 :(得分:6)

正如Scott Wlaschin所指出的那样here,如果你需要将数据作为第一个参数(而不是最后一个)传递到管道链的某个地方,则后向管道运算符很有用 。请考虑以下事项:

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是“生日快乐”,这就是我想要的。