2010-02-25 10 views
6

¿Está el parámetro de tubería en línea funcionando solo para funciones que aceptan un parámetro? Si nos fijamos en el ejemplo de la Chris Smiths' page,Tubería de otro parámetro en la línea en F #


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

donde su función filesUnderFolder esperaba único parámetro RootFolder, lo que si la función estaba esperando dos parámetros, es decir
let filesUnderFolder size rootFolder

Entonces esto no funciona :


// 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 

Como yo puedo definir
let inline (>>) f g x y = g(f x y)
Creo que debería ser capaz de utilizar el operador de tuberías con funciones que tienen múltiples parámetros de entrada, ¿verdad? ¿Qué me estoy perdiendo?

Respuesta

10

Al mezclar los operadores de tuberías y los argumentos al curry ser consciente de la orden para pasar argumentos con.

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

Piénselo como si el compilador pusiera paréntesis alrededor de la función y sus parámetros de esta manera.

@"C:\Users\chrsmith\Pictures\" |> filesUnderFolder size
convierte
@"C:\Users\chrsmith\Pictures\" |> (filesUnderFolder size)
o
(filesUnderFolder size) @"C:\Users\chrsmith\Pictures\"

Fuera de ejemplo para

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

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

1 |> print2 2;; 
2 - 1 

con tres argumentos

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 

Definiciones

let inline (|>) x f = f x 

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

let inline (|||>) (x1,x2,x3) f = f x1 x2 x3 
+0

muchas gracias gradbot, es el valor devuelto en la tubería, ¿puedo tratarlo como un objeto? algo así como: tamaño, @ "C: \ Users \ chrsmith \ Pictures \" ||> filesUnderFolder |> .GetLength() – demokritos

+0

Como objeto no, pero podría crear una nueva función con '(|>)' operador, tampoco hay una manera general de pasar una función miembro como argumento en F #. Tienes que envolverlo en una función. 'size, @" C: \ Users \ chrsmith \ Pictures \ "||> filesUnderFolder |> (diversión x -> x.GetLength())' – gradbot

6

El ejemplo que sugirió debería funcionar bien, a la

let add x y = x + y 

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

Si filesUnderFolder dos argumentos al curry, y que se aplican parcialmente a uno arg, que se puede utilizar en la tubería para el otro.

(Tenga en cuenta también la tubería menos conocido operador ||>

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

que tiene un 2-tupla y se alimentan secuencialmente en lo que sigue.)

+0

|||> también se define en prim- types.fs :) – gradbot

+0

¡Hola! Ese operador de oleoductos es nuevo para mí, sin duda uno para mantener mi manga. – Benjol

+0

Gracias chicos. ahora puedo valor único o tubles, mi siguiente pregunta es ¿puedo agregar una lista/matriz filesUnderFolder |> Seq.map FileInfo mi problema es que no puedo procesar esto con pipeline |>, ¿o no? Assembly.GetExecutingAssembly.GetFiles() demokritos

0

Puede ser mal estilo (?), Pero se puede añadir parámetros adicionales a la tubería 'desde el lado derecho'

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) 
Cuestiones relacionadas