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

unj*_*nj2 30 f#

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

let distanceFromOrigin aPoint =
    let square x = x * x
    sqrt (square aPoint.x + square aPoint.y)
Run Code Online (Sandbox Code Playgroud)

VS

let distanceFromOrigin aPoint =
    let square x = x * x
    sqrt <| square aPoint.x + square aPoint.y
Run Code Online (Sandbox Code Playgroud)

Ram*_*nir 34

由于左边的关联性(f <| g <| x被解析为(f <| g) <| x,可悲的是不f <| (g <| x)等同于x |> g |> f),我发现只有当你想要删除括号(而不是f (long expression)你写的f <| long expression)时它才有用.

  • +1是的,我认为这是重点.(我在你的答案中添加了一些格式 - 希望它没问题) (4认同)

Lau*_*ent 21

之间进行选择f x,x |> f并且f <| x主要是风格的问题.选择一个而不是另一个没有绝对的规则.该|>运营商是非常受欢迎的,它的使用是个好主意.

<|不那么频繁,但如果你查看编译器的来源,你会发现一些用途.例如:

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

if info.precision then
  failwithf "%s" <| FSComp.SR.forFormatDoesntSupportPrecision(ch.ToString())
Run Code Online (Sandbox Code Playgroud)

<|用于删除括号,我认为它使得代码在仔细使用时更具可读性.当您看到它时,您知道以下表达式是您的函数的参数.您不必搜索右括号.我建议你谨慎使用它,你通常应该避免混合<||>相同的表达,因为它可能非常令人困惑.

我有时喜欢使用此运算符来创建带有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
Run Code Online (Sandbox Code Playgroud)

该块基于缩进,因此它非常适合F#代码.多亏了<|操作符,您不需要尾随括号.


MY_*_*Y_G 7

正如Scott Wlaschin在指出的那样,如果您需要将数据作为第一个参数(而不是最后一个)传递到管道链的某个位置,则后向管道运算符非常有用.考虑以下:

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"
Run Code Online (Sandbox Code Playgroud)

amendedString是"生日蹩脚".让我们说我想让它成为"蹩脚的生日".我可以通过使用反向管道运算符来实现:

let amendedString = testString
                    |> replace "H" "Cr"
                    |> joinWith <| "birthday"
Run Code Online (Sandbox Code Playgroud)

现在amendedString是"蹩脚的生日",这就是我想要的.