Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Piping another parameter into the line in F#

Tags:

f#

pipeline

Is piping parameter into line is working only for functions that accept one parameter? If we look at the example at Chris Smiths' page,


// Using the Pipe-Forward operator (|>)
let photosInMB_pipeforward =
    @"C:\Users\chrsmith\Pictures\"
    |> filesUnderFolder
    |> Seq.map fileInfo
    |> Seq.map fileSize
    |> Seq.fold (+) 0L 
    |> bytesToMB

where his filesUnderFolder function was expecting only rootFolder parameter, what if the function was expecting two parameters, i.e.
let filesUnderFolder size rootFolder

Then this does not work:


// Using the Pipe-Forward operator (|>)
let size= 4
let photosInMB_pipeforward =
    @"C:\Users\chrsmith\Pictures\"
    |> filesUnderFolder size
    |> Seq.map fileInfo
    |> Seq.map fileSize
    |> Seq.fold (+) 0L 
    |> bytesToMB

Since I can define
let inline (>>) f g x y = g(f x y)
I think I should be able to use pipeline operator with functions having multiple input parameters, right? What am I missing?

like image 961
demokritos Avatar asked Feb 25 '10 00:02

demokritos


People also ask

What does it mean to pipe a function?

A pipe function takes an n sequence of operations; in which each operation takes an argument; process it; and gives the processed output as an input for the next operation in the sequence. The result of a pipe function is a function that is a bundled up version of the sequence of operations.

What does the pipe operator %>% do?

What does the pipe do? The pipe operator, written as %>% , has been a longstanding feature of the magrittr package for R. It takes the output of one function and passes it into another function as an argument. This allows us to link a sequence of analysis steps.

What is piping in R studio?

Pipes are an extremely useful tool from the magrittr package 1 that allow you to express a sequence of multiple operations. They can greatly simplify your code and make your operations more intuitive. However they are not the only way to write your code and combine multiple operations.


3 Answers

When mixing pipeline operators and curried arguments be aware of the order you pass arguments with.

let size = 4
let photosInMB_pipeforward =
    size, @"C:\Users\chrsmith\Pictures\"
    ||> filesUnderFolder
    |> Seq.map fileInfo
    |> Seq.map fileSize
    |> Seq.fold (+) 0L 
    |> bytesToMB

Think about it as if the compiler is putting parentheses around the function and its parameters like this.

@"C:\Users\chrsmith\Pictures\" |> filesUnderFolder size
becomes
@"C:\Users\chrsmith\Pictures\" |> (filesUnderFolder size)
or
(filesUnderFolder size) @"C:\Users\chrsmith\Pictures\"

Out of order example

let print2 x y = printfn "%A - %A" x y;;

(1, 2) ||> print2;;
1 - 2

1 |> print2 2;;
2 - 1

With three arguments

let print3 x y z = printfn "%A - %A - %A" x y z;;

(1, 2, 3) |||> print3;;
1 - 2 - 3

(2, 3) ||> print3 1;;
1 - 2 - 3

3 |> print3 1 2;;
1 - 2 - 3

Definitions

let inline (|>) x f = f x

let inline (||>) (x1,x2) f = f x1 x2

let inline (|||>) (x1,x2,x3) f = f x1 x2 x3
like image 129
gradbot Avatar answered Sep 25 '22 15:09

gradbot


The example you suggested should work fine, a la

let add x y = x + y

41
|> add 1
|> printfn "%d"

If filesUnderFolder takes two curried args, and you partially apply it to one arg, you can use it in the pipeline for the other.

(Note also the lesser known pipeline operator ||>

(41,1)
||> add
|> printfn "%d"

which takes a 2-tuple and feed them sequentially into what follows.)

like image 26
Brian Avatar answered Sep 25 '22 15:09

Brian


It may be bad style (?), but you can add additional parameters to the pipeline 'from the right side'

let h x y z = x + y - z

let sub x y = x - y

let sqr x = x * x

3 |> h <| 2 <| 7
  |> sub <| 23
  |> sqr

// is the same as
sqr (sub (h 3 2 7) 23)
like image 36
D.F.F Avatar answered Sep 25 '22 15:09

D.F.F