Recherche…


À quoi sert un tuple 0?

Un 2-tuple ou un 3-tuple représentent un groupe d'éléments apparentés. (Points dans l'espace 2D, valeurs RVB d'une couleur, etc.) Un 1-tuple n'est pas très utile car il pourrait facilement être remplacé par un seul int .

Un 0-tuple semble encore plus inutile puisqu'il ne contient absolument rien . Pourtant, il a des propriétés qui le rendent très utile dans les langages fonctionnels comme F #. Par exemple, le type 0-tuple a exactement une valeur, généralement représentée par () . Tous les 0-tuples ont cette valeur, c'est donc essentiellement un type singleton. Dans la plupart des langages de programmation fonctionnels, y compris F #, cela s'appelle le type d' unit .

Les fonctions qui renvoient un void dans C # retourneront le type d' unit dans F #:

let printResult = printfn "Hello"

Exécutez cela dans l'interpréteur interactif F # et vous verrez:

val printResult : unit = ()

Cela signifie que la valeur printResult est de type unit et a la valeur () (le tuple vide, la seule et unique valeur du type d' unit ).

Les fonctions peuvent également prendre le type d' unit comme paramètre. En F #, les fonctions peuvent sembler ne prendre aucun paramètre. Mais en fait, ils prennent un seul paramètre de type unit . Cette fonction:

let doMath() = 2 + 4

est en fait équivalent à:

let doMath () = 2 + 4

C'est-à-dire une fonction qui prend un paramètre de type unit et renvoie la valeur int 6. Si vous regardez la signature de type que l'interpréteur interactif F # imprime lorsque vous définissez cette fonction, vous verrez:

val doMath : unit -> int

Le fait que toutes les fonctions prennent au moins un paramètre et renvoie une valeur, même si cette valeur est parfois une valeur "inutile" comme () , signifie que la composition de la fonction est beaucoup plus facile dans F # que dans les langues qui type d' unit . Mais c'est un sujet plus avancé auquel nous reviendrons plus tard. Pour l'instant, rappelez-vous simplement que lorsque vous voyez l' unit dans une signature de fonction, ou () dans les paramètres d'une fonction, c'est le type 0-tuple qui sert à dire "Cette fonction prend ou retourne aucune valeur significative."

Différer l'exécution du code

Nous pouvons utiliser le type d' unit comme argument de fonction pour définir des fonctions que nous ne voulons pas exécuter plus tard. Ceci est souvent utile dans les tâches d'arrière-plan asynchrones, lorsque le thread principal peut vouloir déclencher certaines fonctionnalités prédéfinies du thread d'arrière-plan, comme le déplacer dans un nouveau fichier ou si une let-binding ne doit pas être exécutée immédiatement:

module Time =
    let now = System.DateTime.Now   // value is set and fixed for duration of program
    let now() = System.DateTime.Now // value is calculated when function is called (each time)

Dans le code suivant, nous définissons le code pour démarrer un "worker" qui imprime simplement la valeur sur laquelle il travaille toutes les 2 secondes. Le travailleur retourne alors deux fonctions qui peuvent être utilisées pour le contrôler - une qui le déplace vers la valeur suivante sur laquelle travailler et une qui l'empêche de fonctionner. Celles-ci doivent être des fonctions, car nous ne voulons pas que leurs corps soient exécutés jusqu'à ce que nous choisissions de le faire, sinon le travailleur passerait immédiatement à la seconde valeur et s'arrêterait sans avoir rien fait.

let startWorker value =
    let current = ref value
    let stop = ref false
    let nextValue () = current := !current + 1
    let stopOnNextTick () = stop := true
    let rec loop () = async {
        if !stop then
            printfn "Stopping work."
            return ()
        else
            printfn "Working on %d." !current
            do! Async.Sleep 2000
            return! loop () }
    Async.Start (loop ())
    nextValue, stopOnNextTick

Nous pouvons alors démarrer un travailleur en faisant

let nextValue, stopOnNextTick = startWorker 12

et le travail va commencer - si nous sommes en F # interactif, nous verrons les messages imprimés dans la console toutes les deux secondes. Nous pouvons alors courir

nextValue ()

et nous verrons les messages indiquant que la valeur en cours de traitement est passée à la suivante.

Quand il est temps de finir de travailler, nous pouvons exécuter le

stopOnNextTick ()

fonction, qui va imprimer le message de fermeture, puis quitter.

Le type d' unit est important ici pour signifier "aucune entrée" - les fonctions ont déjà toutes les informations dont elles ont besoin pour travailler avec elles, et l'appelant n'est pas autorisé à changer cela.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow