Buscar..


¿De qué sirve una tupla 0?

Una tupla de 2 o una tupla de 3 representa un grupo de elementos relacionados. (Puntos en el espacio 2D, valores RGB de un color, etc.) Una tupla 1 no es muy útil ya que podría reemplazarse fácilmente con un solo int .

Un 0-tuple parece aún más inútil ya que no contiene absolutamente nada . Sin embargo, tiene propiedades que lo hacen muy útil en lenguajes funcionales como F #. Por ejemplo, el tipo de tupla 0 tiene exactamente un valor, generalmente representado como () . Todas las tuplas 0 tienen este valor, por lo que es esencialmente un tipo singleton. En la mayoría de los lenguajes de programación funcionales, incluido F #, esto se denomina tipo de unit .

Las funciones que devuelven void en C # devolverán el tipo de unit en F #:

let printResult = printfn "Hello"

Ejecute eso en el intérprete interactivo de F #, y verá:

val printResult : unit = ()

Esto significa que el valor printResult es de tipo unit y tiene el valor () (la tupla vacía, el único valor del tipo de unit ).

Las funciones también pueden tomar el tipo de unit como un parámetro. En F #, las funciones pueden parecer que no están tomando parámetros. Pero, de hecho, están tomando un solo parámetro de tipo unit . Esta función:

let doMath() = 2 + 4

es en realidad equivalente a:

let doMath () = 2 + 4

Es decir, una función que toma un parámetro de tipo unit y devuelve el valor int 6. Si observa la firma de tipo que el intérprete interactivo F # imprime cuando define esta función, verá:

val doMath : unit -> int

El hecho de que todas las funciones tomarán al menos un parámetro y devolverá un valor, incluso si ese valor es a veces un valor "inútil" como () , significa que la composición de la función es mucho más fácil en F # que en idiomas que no tienen el tipo de unit . Pero ese es un tema más avanzado que veremos más adelante. Por ahora, solo recuerde que cuando ve la unit en la firma de una función, o () en los parámetros de una función, ese es el tipo de tupla 0 que sirve para decir "Esta función toma, o devuelve, valores no significativos".

Aplazar la ejecución del código

Podemos usar el tipo de unit como un argumento de función para definir funciones que no queremos que se ejecuten hasta más adelante. A menudo, esto es útil en tareas en segundo plano asíncronas, cuando el subproceso principal puede querer activar alguna funcionalidad predefinida del subproceso en segundo plano, como moverlo a un nuevo archivo, o si no se debe ejecutar un enlace let de inmediato:

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)

En el siguiente código, definimos el código para iniciar un "trabajador" que simplemente imprime el valor en el que está trabajando cada 2 segundos. Luego, el trabajador devuelve dos funciones que pueden usarse para controlarlo: una que lo mueve al siguiente valor para trabajar, y otra que lo detiene de funcionar. Estas deben ser funciones, ya que no queremos que sus cuerpos se ejecuten hasta que decidamos hacerlo, de lo contrario, el trabajador pasaría inmediatamente al segundo valor y cerraría sin haber hecho nada.

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

Entonces podemos empezar un trabajador haciendo

let nextValue, stopOnNextTick = startWorker 12

y el trabajo comenzará - si estamos en F # interactivo, veremos los mensajes impresos en la consola cada dos segundos. Entonces podemos correr

nextValue ()

y veremos los mensajes que indican que el valor en el que se está trabajando se ha movido al siguiente.

Cuando es hora de terminar de trabajar, podemos ejecutar el

stopOnNextTick ()

Función, que imprimirá el mensaje de cierre, luego saldrá.

El tipo de unit es importante aquí para indicar "sin entrada": las funciones ya tienen toda la información que necesitan para trabajar, y la persona que llama no tiene permitido cambiar eso.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow