F # - la création de délégués
Question
en train de lire une série de F # sur blogposts, destiné au programmeur C #. En ce moment, la lecture que j'ai terminé la partie 3 ( http://www.jelovic.com/weblog/ ? p = 220 ) et suis resté perplexe.
La différence entre
let readLine = Console.ReadLine ()
et
let readLine () = Console.ReadLine ()
est assez clair, mais pourquoi est-il nécessaire de préciser les deux accolades - () - dans la ligne suivante:
let impression (texte: string) () = text Console.WriteLine
ne doit pas être le compilateur en mesure de déterminer vous déclarer une impression de délégué en omettant les accolades, il se présente comme suit:
let impression (texte: string) = text Console.WriteLine
En outre, la ligne suivante m'a fait peu de sens
Habituellement, lorsque vous avez une fonction qui prend des paramètres d'un type différent le compilateur peut faire la différence entre un appel de fonction et une référence de délégué, mais pour l'unité que vous devez forcer.
Est-ce que cela signifie que lorsque les paramètres sont différents, il est sûr que le compilateur suppose qu'il est un appel de fonction?
merci à vous tous pour les réponses, il est clair pour moi maintenant. Quant à la citation, nous allons laisser reposer.
La solution
Introduction. Je pense qu'il est utile d'examiner d'abord la différence de l'exemple simple car il aide à comprendre ce que la valeur « unité » est. La première déclaration crée une valeur de chaîne (et appelle immédiatement ReadLine
pour obtenir l'entrée de l'utilisateur):
> let readLine = Console.ReadLine ();;
val readLine : string
La seconde déclaration crée une fonction qui prend la valeur unitaire comme argument. La fonction n'a pas besoin de prendre une entrée, mais nous voulons le définir en fonction, afin qu'il puisse être exécuté à plusieurs reprises (nous en avons besoin, parce que la fonction a effet secondaire - il lit entrée de l'utilisateur).
Le paramètre « unité » est juste une façon de créer une fonction qui prend quelque chose comme argument. « Unité » ne dispose que d'une seule valeur écrite comme ()
, il ne représente aucune information - juste le fait qu'il ya un paramètre:
> let readLine () = Console.ReadLine ();;
val readLine : unit -> string
Votre question. Pour regarder votre exemple avec des accolades supplémentaires. Cela crée une fonction qui prend une chaîne de caractères en tant que premier paramètre et prend la valeur « unitaire » supplémentaire en tant que second paramètre. Vous pouvez voir que de la signature de type:
> let print (text : string) () = Console.WriteLine text
val print : string -> unit -> unit
Ceci est valable F # déclaration, mais il est pas très utile. Cela signifie que la fonction sera appelée que lorsque vous donnez une chaîne à imprimer et aussi la valeur « unité » supplémentaire. Vous pouvez l'appeler comme ceci:
print "Hello" ()
Même sans le paramètre « unité » supplémentaire, ce serait une fonction (par opposition à une valeur), afin d'ajouter le paramètre supplémentaire ne aide (vous créez toujours une fonction qui peut être appelée à imprimer des chaînes différentes ).
Il y a encore des cas où cette déclaration peut être intéressante. Par exemple, vous pouvez appeler la fonction juste avec la chaîne en tant que paramètre. Dans ce cas, vous aurez une fonction à la suite. La fonction de retour prendra unité et imprimera la chaîne:
let f = print "Hello" // doesn't print anything
f () // prints "Hello"
f () // prints "Hello" again!
Ainsi, le compilateur vous permet d'utiliser des valeurs « unitaires » comme toutes les autres valeurs dans la langue. Cela inclut les utilisations qui peuvent paraître un peu familier (et pas très utile) au début, mais peut faire un bon sens dans un scénario.
Autres conseils
let print (text : string) = Console.WriteLine text
crée une méthode d'impression comme:
print "hi" // prints "hi" in the console
où:
let print (text : string) () = Console.WriteLine text
produit une méthode pour imprimer une chaîne spécifique comme:
let printHi = print "hi" // Does NOT print a string to the console
printHi () // But now this does print "hi" :)
printHi () // And this...
Donc, essentiellement, il est une usine « impression chaîne spécifique à la fonction X de la console » dont le résultat (ex printHi) peut être réutilisé plusieurs fois.
Utilisation curryfication,
let makePrinter (text : string) () = Console.WriteLine text
nous allons vous créer une fonction qui imprime toujours une certaine chaîne, par exemple
let helloPrinter = makePrinter "hello"
donne "bonjour" en appelant simplement
helloPrinter ()
Par contre,
let print (text : string) = Console.WriteLine text
Sorties immediat "texte" si elle est appelée
print "hello"
et les retours (), et non pas une fonction de type unit -> unit
comme dans le premier, le curry cas.