Avaluació tardana
En programació d'ordinadors, avaluació tardana (en anglès: Lazy evaluation) és la tècnica de retardar un càlcul fins que se'n requereixi el resultat.
Els beneficis de l'avaluació tardana inclouen:
- augment de rendiment en evitar el càlcul d'expressions no requerides, evitant a més els errors que s'hi puguin produir.
- capacitat de construir estructures de dades de llargada infinita
- capacitat de definir estructures de control com a abstraccions en comptes de comandes.
El contrari de l'avaluació tardana és l'avaluació primerenca (en anglès: eager evaluation), també anomenada avaluació estricta, on una expressió és avaluada tan bon punt és assignada a una variable o paràmetre. L'avaluació primerenca és el comportament utilitzat en la majoria de llenguatges.
L'avaluació tardana comprèn els següents tres conceptes:
- L'expressió només s'avalua quan és requerida per la funció que la requereix (avaluació retardada).
- L'expressió només s'avalua fins a l'extensió requerida (avaluació curtcircuitada)
- L'expressió mai no s'avalua més d'una vegada (avaluació en l'ordre aplicatiu)[1]
El llenguatge Haskell utilitza majoritàriament l'avaluació tardana.
Altres llenguatges com OCaml, Scheme[2] i altres la incorporen de manera opcional, mitjançant construccions explícites.
Exemples
Llistes d'avaluació tardana en OCaml
open Printf ;; (* tipus de llista d'avaluació tardana (ang:lazy) *) type 'a node_t = | Nil | Cons of 'a * 'a zlist_t and 'a zlist_t = 'a node_t Lazy.t ;; (** generador tardà de m elements; ''lazy'' deixa la generació en suspens *) let rec genera_llista (m:int) :'a zlist_t = lazy (match m with | 0 -> Nil | n -> Cons(n, genera_llista (n-1)) ) ;; (** fold_left_tard: aplica una op. binària sobre un acumulador i els elem. d'una llista d'avaluació tardana *) let rec fold_left_tard f acum (llista:'a zlist_t) = match (Lazy.force llista) with (* força l'avaluació del generador de la llista obtenint-ne 1 elem. *) | Nil -> acum | Cons(x, xs) -> fold_left_tard f (f acum x) xs ;; let op_binaria = fun (a:float) (b:int) -> a +. sqrt (float_of_int b) ;; (* qualsevol que interessi *) let _ = printf "resultat: %.2f\n" (fold_left_tard op_binaria 0. (genera_llista 100000)) ;;