2009-11-30 15 views
8

Se puede pasar en una operación como la "división por 2" o "restar 1" usando sólo un operador parcialmente aplicada, donde "añadir al menos 1" es el siguiente:F # pasar un operador con argumentos a una función

List.map ((+) 1) [1..5];; //equals [2..6] 
// instead of having to write: List.map (fun x-> x+1) [1..5] 

lo que pasa es 1 se está aplicando a (+) ya que es el primer argumento, y el elemento de la lista se está aplicando como segundo argumento. Para la suma y la multiplicación, este orden de argumento no importa.

Supongamos que quiero restar 1 a cada elemento (esto probablemente será un principiantes error común):

List.map ((-) 1) [1..5];; //equals [0 .. -4], the opposite of what we wanted 

1 se aplica a la (-) como primer argumento, así que en vez de (list_item - 1), me obtener (1 - list_item). Puedo volver a escribir como la adición de uno negativo en lugar de restar positivo:

List.map ((+) -1) [1..5];; 
List.map (fun x -> x-1) [1..5];; // this works too 

Estoy buscando una manera más expresiva de escribirlo, algo así como ((-) _ 1), donde _ denota un marcador de posición, al igual que en el lenguaje de Arco. Esto causaría 1 para ser el segundo argumento de -, por lo que en List.map, se evaluaría a list_item - 1. Así que si quería para mapear divide by 2 a la lista, se podría escribir:

List.map ((/) _ 2) [2;4;6] //not real syntax, but would equal [1;2;3] 
List.map (fun x -> x/2) [2;4;6] //real syntax equivalent of the above 

se puede hacer esto o tengo que usar (fun x -> x/2)? Parece que lo más cerca que podemos llegar a la sintaxis marcador de posición es utilizar un lambda con un argumento con nombre.

Respuesta

11

podría escribir una función del tirón, algo así como:

let flip f x y = f y x 

List.map (flip (-) 1) [2;4;6] 

que pueda tener la sintaxis incorrecta, no estoy terriblemente fluidez en F #.

+8

Su función flip-puede (también) definirse como 'let flip f x y = f y x' –

+0

Es un buen candidato para la alineación. –

8

no hay '' secciones de operación en F #, al estilo de Haskell, ni argumentos de marcador de posición (al parecer, a la ARC). Se puede utilizar un combinador 'flip' como se sugiere en otra respuesta para invertir el orden de los argumentos y luego aplicar parcialmente la primera (ahora segundo) argumento.

Pero yo sólo tiene que utilizar

fun x -> x/2 

A menos que estés jugando código de golf, no creo que tratando de afeitarse unos pocos caracteres de aquí se compra nada.

8

El flip solución al sugerido por Logan Capaldo también se puede escribir usando un operador (aquí >.):

let (>.) x f = (fun y -> f y x) 
List.map (1 >. (-)) [2;4;6] 

O si lo prefiere los operandos al revés:

let (>.) f x = (fun y -> f y x) 
List.map ((-) >. 1) [2;4;6] 

Editar : el uso de un operador que "se parece más a un marcador de posición" (aquí >-<) se pone muy cerca de su sintaxis sugerida:

List.map ((-) >-< 1) [2;4;6] 

'_' es por desgracia (?) No a valid operator symbol in F#.

+1

:) Smiley. :(frownie.: p tongue.> - . un ojo asomó ... (frownie con un ojo asomó. – Juliet

Cuestiones relacionadas