Domanda

Al momento la lettura di una serie di post sul blog relativi F #, destinato al programmatore C #. leggendo in questo momento ho finito parte 3 ( http://www.jelovic.com/weblog/ ? p = 220 ) e sto lasciato perplessi.

La differenza tra

  

lasciare readLine = Console.ReadLine ()

e

  

lasciare readLine () = Console.ReadLine ()

è abbastanza chiaro, ma perché c'è la necessità di specificare i due bretelle - () - nella seguente riga:

  

lasciare stampa (text: String) () = testo Console.WriteLine

Nel caso non il compilatore sia in grado di capire che stai dichiarando una stampa delegato omettendo le parentesi graffe, quindi sarebbe il seguente aspetto:

  

lasciare stampa (text: String) = testo Console.WriteLine

Inoltre, la seguente riga di fatto poco senso per me

  

Di solito quando si dispone di una funzione che accetta parametri di tipo diverso il compilatore può distinguere tra una chiamata di funzione e un riferimento delegato, ma per l'unità bisogna forzarlo.

Questo significa che quando i parametri sono diversi è sicuro per il compilatore per scontato che sia una funzione chiamata?

Grazie a tutti per le risposte, è chiaro per me ora. Per quanto riguarda la citazione, ve lo faremo riposare.

È stato utile?

Soluzione

Introduzione. Penso che sia utile discutere prima la differenza del semplice esempio in quanto aiuta a capire che cosa "unità" è il valore. La prima dichiarazione crea un valore stringa (e richiama immediatamente ReadLine avere l'input dall'utente):

> let readLine = Console.ReadLine ();;
val readLine : string

La seconda dichiarazione crea una funzione che assume valore unitario come argomento. La funzione non ha bisogno di prendere alcun input, ma vogliamo definirlo come una funzione, in modo che possa essere eseguito più volte (abbiamo bisogno che, perché la funzione ha effetto collaterale - si legge input dall'utente).

Il parametro "unità" è solo un modo di creare una funzione che prende qualcosa come argomento. "Unit" ha solo un valore singolo scritto come (), in modo che non rappresenta alcuna informazione - solo il fatto che ci sia qualche parametro:

> let readLine () = Console.ReadLine ();;
val readLine : unit -> string

La tua domanda. Per guardare il vostro esempio con bretelle supplementari. Questo crea una funzione che prende una stringa come primo parametro e richiede ulteriore valore "unità" come il secondo parametro. Si può vedere che dalla firma di tipo:

> let print (text : string) () = Console.WriteLine text 
val print : string -> unit -> unit

Questo è valido F # dichiarazione, ma non è molto utile. Ciò significa che la funzione sarà chiamata solo quando si dà una certa stringa da stampare e anche un valore aggiunto "unità". È possibile chiamare in questo modo:

print "Hello" ()

Anche senza il parametro aggiuntivo "unità", sarebbe una funzione (al contrario di un valore), in modo da aggiungere il parametro aggiuntivo non aiuta (si sta creando sempre una funzione che può essere chiamata per stampare diverse stringhe ).

Non ci sono ancora casi in cui questa Dichiarazione possano essere interessanti. Ad esempio, è possibile chiamare la funzione solo con la stringa come parametro. In questo caso, si otterrà una funzione come il risultato. La funzione restituita avrà unità e stamperà la stringa:

let f = print "Hello" // doesn't print anything
f ()                  // prints "Hello"
f ()                  // prints "Hello" again!

Quindi, il compilatore permette di utilizzare i valori "Unità" come tutti gli altri valori nella lingua. Questo include usi che possono sembrare un po 'poco familiare (e non molto utile) in un primo momento, ma possono fare un buon senso in qualche scenario.

Altri suggerimenti

Questa:

let print (text : string) = Console.WriteLine text

crea un metodo per stampare come:

print "hi" // prints "hi" in the console

dove:

let print (text : string) () = Console.WriteLine text

produce un metodo per stampare una stringa specifica come:

let printHi = print "hi" // Does NOT print a string to the console

printHi () // But now this does print "hi" :)
printHi () // And this...

Quindi, in sostanza, si tratta di una "stampa stringa specifica X alla funzione di console" fabbrica che il risultato (ex printHi) può essere riutilizzato più volte.

Utilizzando currying,

let makePrinter (text : string) () = Console.WriteLine text

ti permette di creare una funzione che stampa sempre una certa stringa, per esempio

let helloPrinter = makePrinter "hello"

dà "ciao", semplicemente chiamando

helloPrinter ()

D'altra parte,

let print (text : string) = Console.WriteLine text

uscite immediatamente "testo", se chiamato

print "hello"

e restituisce (), non una funzione di tipo unit -> unit come nel primo, caso curry.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top