tags:

views:

155

answers:

2

Hi, 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?

+6  A: 

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.)

Brian
|||> is also defined in prim-types.fs :)
gradbot
Hey! That pipeline operator is new to me, definitely one to keep up my sleeve.
Benjol
Thanks guys. now I can single value or tubles, my next question is can I add a list/array<code>filesUnderFolder |> Seq.map FileInfo </code>my problem is I can't process this with pipeline |>, or can I? <code>Assembly.GetExecutingAssembly.GetFiles()</code>
demokritos
+3  A: 

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
gradbot
thanks a lot gradbot,is the value returned from on pipeline, can I treat it as an object? something like: size, @"C:\Users\chrsmith\Pictures\" ||> filesUnderFolder |> .GetLength()
demokritos
As an object no but you could create a new function with the `(|>)` operator, also there is no general way to pass a member function as an argument in F#. You have to wrap it in a function. `size, @"C:\Users\chrsmith\Pictures\" ||> filesUnderFolder |> (fun x -> x.GetLength())`
gradbot