2012-03-18 8 views
5

El documento de Lazy.lazy_from_val establece que esta función es para casos especiales:¿Cuál es el propósito de Lazy.lazy_from_val de OCaml?

val lazy_from_val : 'a -> 'a t 
    lazy_from_val v returns an already-forced suspension of v This is for special purposes only and should not be confused with lazy (v). 

Qué casos están hablando?

Si creo un par de cómputo suspendido de un valor como:

let l1 = lazy 123 
let l2 = Lazy.lazy_from_val 123 

¿Cuál es la diferencia entre estos dos? Porque Lazy.lazy_is_val l1 y Lazy.lazy_is_val l2 ambos devuelven verdadero diciendo que el valor ya está forzado!

Respuesta

7

El propósito especial sería si se necesita un valor perezoso pero a veces tienen un valor ya computarizada (no perezoso). Puede usar lazy_from_val para convertir un valor ya calculado en una versión perezosa (forzada) de su valor.

let f lazyint = 
    Lazy.force lazyint + 42 

let li = lazy 4;; 

# f li;; 
- : int = 46 
# f 14;; 
    ^^ 
Error: This expression has type int but an expression was expected of type 
     int Lazy.t = int lazy_t 
# f (Lazy.lazy_from_val 14);; 
- : int = 56 

En este ejemplo (artificial), es posible que desee llamar a f con un valor entero ordinario (14, en este ejemplo). Puede hacerlo, pero necesita usar Lazy.lazy_from_val para que funcione.

La diferencia clave es que lazy toma una expresión de tipo 'a y crea un cómputo suspendido (en esencia, un cierre) de tipo 'a lazy_t. Lazy.lazy_from_val toma un valor pre-calculado del tipo 'a y lo convierte en un valor (pre-forzado) del tipo 'a lazy_t. Si la expresión tiene efectos secundarios, se puede ver la diferencia entre los dos.

# let p() = print_string "here\n"; 3 ;; 
val p : unit -> int = <fun> 
# let l1 = lazy (p());; 
val l1 : int lazy_t = <lazy> 
# let l2 = Lazy.lazy_from_val (p());; 
here 
val l2 : int Lazy.t = lazy 3 
# f l1;; 
here 
- : int = 45 
# f l2;; 
- : int = 45 
# 

Puede implementar operaciones diferidas directamente utilizando cierres y referencias explícitos. Como señala Matthias Benkard, el mecanismo perezoso de OCaml usa una sintaxis especial para que sea menos complicado trabajar con él. Es decir, lazy es una palabra clave OCaml, no una función.

+0

¡Gracias por la explicación! – Ricardo

+1

"El mecanismo diferido de OCaml usa sintaxis especial" ... y funciones especiales de GC para eliminar la indirección, que se ha vuelto inútil, a los valores forzados. –

+0

¡Muy bueno saberlo, gracias! (¿Hay una buena referencia para esto?) –

2

lazy_from_val es una función en lugar de sintaxis. Por lo tanto,

# let id = fun x -> x;; 
val id : 'a -> 'a = <fun> 
# Lazy.lazy_is_val (lazy (id 123));; 
- : bool = false 
# Lazy.lazy_is_val (Lazy.lazy_from_val (id 123));; 
- : bool = true 
Cuestiones relacionadas