2010-06-03 16 views
14

Estoy trabajando en una tarea de tarea en la que se nos pide que implementemos una estrategia de evaluación llamada "llamar por nombre" en un determinado idioma que desarrollamos (usando Scheme).¿Qué es "Llamar por nombre"?

Nos dieron un example in Scala, pero no entiendo cómo funciona "llamar por nombre" y cómo es diferente a "llamar por necesidad"?

Respuesta

23

Llamada por necesidad es una versión memorada de llamada por nombre (ver wikipedia).

En llamada por nombre, el argumento se evalúa cada vez que se utiliza, mientras que en la llamada por necesidad, se evalúa la primera vez que se utiliza, y el valor registrado de manera que posteriormente lo necesitan no ser reevaluado

+0

ya he implementado llamada por necesidad, y cuando Lo estaba haciendo la primera implementación sin almacenamiento en caché, no tengo sentido para mí que el profesor me pida que haga algo que ya hice, porque quiero entender la verdadera diferencia entre llamar por necesidad y llamar por nombre – forellana

+0

confirmé con el profesor, que es llamada por nombre, estaba confundido porque ya escribimos ese código y ahora nos está preguntando nuevamente por ese – forellana

9

Llamar por nombre es un esquema de paso de parámetros donde se evalúa el parámetro cuando se usa, no cuando se llama a la función. Aquí hay un ejemplo en pseudo-C:

int i; 
char array[3] = { 0, 1, 2 }; 

i = 0; 
f(a[i]); 

int f(int j) 
{ 
    int k = j; // k = 0 
    i = 2;  // modify global i 
    k = j;  // The argument expression (a[i]) is re-evaluated, giving 2. 
} 

La expresión argumento se evalúa perezosamente cuando se accede utilizando los valores actuales de la expresión argumento.

+0

La evaluación diferida se evalúa como máximo una vez, la llamada por nombre se evalúa cero, una o más veces. –

+0

no necesariamente: http://en.wikipedia.org/wiki/Lazy_evaluation –

+0

No sé sobre Scheme, pero en Scala (que no tiene parámetros perezosos), esa distinción es completamente precisa. –

2

añadir esto a las respuestas anteriores:

trabajo a través de la SICP section on Streams. Ofrece una buena explicación tanto de la llamada por nombre como de la llamada por necesidad. También muestra cómo implementarlos en Scheme. Por cierto, si usted está buscando una solución rápida que aquí hay una llamada por necesidad implementado en el esquema básico:

;; Returns a promise to execute a computation. (implements call-by-name) 
;; Caches the result (memoization) of the computation on its first evaluation 
;; and returns that value on subsequent calls. (implements call-by-need) 
(define-syntax delay 
    (syntax-rules() 
     ((_ (expr ...)) 
     (let ((proc (lambda() (expr ...))) 
      (already-evaluated #f) 
      (result null)) 
     (lambda() 
      (if (not already-evaluated) 
       (begin 
       (display "computing ...") (newline) 
       (set! result (proc)) 
       (set! already-evaluated #t))) 
      result))))) 

;; Forces the evaluation of a delayed computation created by 'delay'. 
(define (my-force proc) (proc)) 

una muestra de ejecución:

> (define lazy (delay (+ 3 4))) 
> (force lazy) 
computing ... ;; Computes 3 + 4 and memoizes the result. 
7 
> (my-force lazy) 
7 ;; Returns the memoized value. 
+0

'delay' y' force' son r5rs, ¿no? en realidad, al menos tan viejo como r3rs. –

+0

@sgm sí, son parte del estándar. Solo quería mostrar cómo pueden implementarse. –

Cuestiones relacionadas