2009-11-30 11 views
8

Potete passare in un'operazione come "dividere per 2" o "sottrarre 1" utilizzando solo un operatore parzialmente applicata, dove "aggiungere 1" si presenta così:F # passando un operatore con gli argomenti a una funzione

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

Quello che sta succedendo è che 1 viene applicato a (+) come primo argomento e l'elemento della lista viene applicato come secondo argomento. Per addizione e moltiplicazione, questo ordinamento di argomenti non ha importanza.

Supponiamo che voglio sottrarre 1 da ogni elemento (questo sarà probabilmente un principiante errore comune):

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

1 viene applicato alla (-) come primo argomento, così invece di (list_item - 1), I ottenere (1 - list_item). Posso riscriverlo come l'aggiunta di uno negativo invece di sottrarre positiva:

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

Sto cercando un modo più espressivo di scriverlo, qualcosa come ((-) _ 1), dove _ indica un segnaposto, come nella lingua Arc. Ciò farebbe sì che 1 diventi il ​​secondo argomento a -, quindi in List.map verrà valutato su list_item - 1. Quindi, se si voleva mappare divide by 2 alla lista, si potrebbe scrivere:

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 

si può fare o devo usare (fun x -> x/2)? Sembra che la cosa più vicina alla sintassi del segnaposto sia quella di usare un lambda con un argomento con nome.

risposta

11

si potrebbe scrivere una funzione di vibrazione, qualcosa di simile:

let flip f x y = f y x 

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

io possa avere la sintassi sbagliata, io non sono terribilmente fluente in F #.

+8

La funzione flip può essere definita come "flip f x y = f y x" –

+0

Questo è un buon candidato per l'inlining. –

8

Non ci sono "sezioni operative" in F #, a la Haskell, né argomenti di segnaposto (apparentemente a la Arc). È possibile utilizzare un combinatore "flip" come suggerito in un'altra risposta per invertire l'ordine degli argomenti e quindi applicare parzialmente il primo argomento (ora secondo).

Ma vorrei solo usare

fun x -> x/2 

A meno che non si sta giocando a golf in codice, non credo che cercando di radere un altro paio di personaggi fuori qui si compra nulla.

8

Il flip -solution suggerito da Logan Capaldo può anche essere scritta utilizzando un operatore di (qui >.):

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

Oppure, se preferite gli operandi il contrario:

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

Edit : Utilizzando un operatore che "sembra più un segnaposto" (qui >-<) ti avvicini molto alla sintassi suggerita:

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

"_" è sfortunatamente (?) Non a valid operator symbol in F#.

+1

:) Faccina. :(frownie.: p lingua.> - . un occhio spuntò ... (aggrottando le sopracciglia con un occhio. – Juliet