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.
¡Gracias por la explicación! – Ricardo
"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. –
¡Muy bueno saberlo, gracias! (¿Hay una buena referencia para esto?) –