Why does the pipe operator work?

前端 未结 4 1110
一个人的身影
一个人的身影 2021-02-13 12:44

If the pipe operator is created like this:

let (|>) f g = g f

And used like this:

let result = [2;4;6] |> List.map (fun x         


        
4条回答
  •  太阳男子
    2021-02-13 13:27

    The pipe operator is simply syntactic sugar for chained method calls. It's very similar to how linq expressions are expressed in C#.

    Explanation from here:

    Forward Pipe Operator I love this guy. The Forward pipe operator is simply defined as:

    let (|>) x f = f x
    

    And has a type signature:

    'a -> ('a -> 'b) -> 'b
    

    Which translates to: given a generic type 'a, and a function which takes an 'a and returns a 'b, then return the application of the function on the input.

    Rather than explaining this, let me give you an example of where it can be used:

    // Take a number, square it, then convert it to a string, then reverse that string
    let square x         = x * x
    let toStr (x : int)  = x.ToString()
    let rev   (x : string) = new String(Array.rev (x.ToCharArray()))
    
    // 512 -> 1024 -> "1024" -> "4201"
    let result = rev (toStr (square 512))
    

    The code is very straight forward, but notice just how unruly the syntax looks. All we want to do is take the result of one computation and pass that to the next computation. We could rewrite it by introducing a series of new variables:

    let step1 = square 512
    let step2 = toStr step1
    let step3 = rev step2
    let result = step3
    

    But now you need to keep all those temporary variables straight. What the (|>) operator does is take a value, and 'forward it' to a function, essentially allowing you to specify the parameter of a function before the function call. This dramatically simplifies F# code by allowing you to pipe functions together, where the result of one is passed into the next. So to use the same example the code can be written clearly as:

    let result = 512 |> square |> toStr |> rev
    

    Edit:

    In F# what you're really doing with a method call is taking a function and then applying it to the parameter that follows, so in your example it would be List.map (fun x -> x * x * x) is applied to [2;4;6]. All that the pipe operator does is take the parameters in reverse order and then do the application reversing them back.

    function: List.map (fun x -> x * x * x) parameter: [2;4;6]

    Standard F# call syntax: f g

    Reversed F# call syntax: g f

    Standard:

    let var = List.map (fun x -> x * x * x) [2;4;6]
    

    Reversed:

    let var = [2;4;6] |> List.map (fun x -> x * x * x)
    

提交回复
热议问题