2012-07-05 10 views
5

Considere el siguiente código:¿Por qué las continuaciones no tienen una utilidad útil?

(call-with-values 
    (lambda() 
     (call/cc (lambda (k) 
     (k k k)))) 
    (lambda (x y) 
    (procedure-arity y))) 

Es bastante obvio aquí que la continuación en el punto de la llamada call/cc es la lambda en el lado derecho, por lo que su aridad debe ser 2. Sin embargo, el valor de retorno de lo anterior (en Raqueta) es (arity-at-least 0) en su lugar.

De hecho, ejecutar un código similar en Guile (sustituyendo procedure-minimum-arity por procedure-arity) muestra que la continuación también supuestamente permite cualquier número de argumentos, aunque claramente no es el caso.

Entonces, ¿por qué es eso? Por lo que yo entiendo (corríjanme si mi entendimiento es incorrecto), la ariadidad de una continuación es bastante simple: es 1 excepto en el contexto de call-with-values, en cuyo caso es lo que sea el arito del lambda del lado derecho. (Lo cual, es cierto, puede ser complicado si es un case-lambda o similares, pero no es más complicado que si estuviera llamando (procedure-arity (case-lambda ...)) directamente.)

+0

OMI, debería ser cualquier número de argumentos, como cuando se crea la continuación explícita con llamada/cc, el contexto es desconocido hasta la continuación se llama en realidad. Creo que la definición de 'valores' en la especificación (R5/6) lo resume muy bien. – leppie

+0

No estoy muy seguro de cómo 'values' implica que la continuación tiene arity arbitrario. No puede devolver un número diferente de valores de lo que admite la continuación. :-) Por lo tanto, '(+ (valores 1 2 3) 42)' no es válido: en este contexto (asumiendo 'values' como se define en R5RS), la continuación así creada tiene arity 1, nada más. –

+1

También con 'call-with-values', el * consumer * determina la arity, no el * producer *. – leppie

Respuesta

2

Una forma más sencilla de ver la misma es:

(call-with-values 
    (lambda() (error 'arity "~v" (procedure-arity (call/cc (λ (k) k))))) 
    (lambda (x y) (procedure-arity y))) 

y aún más simple:

(procedure-arity (call/cc (λ (x) x))) 

Y por su pregunta - es claro en el primer caso que se espera que la continuación de dos entradas, pero casos como que no son demasiado comunes. Por ejemplo, generalmente son ejemplos, mientras que el "código real" usaría define-values o tiene alguna continuación desconocida, donde las continuaciones que crea call/cc pueden tener aries diferentes dependiendo del contexto en el que fueron creadas. Esto significa que no tiene mucho sentido tratar de descubrir estos raros casos en los que se conoce la razón de la continuación.

Nota:

;; nonsensical, but shows the point 
(define (foo) (call/cc (λ (x) x))) 
(define x (foo)) 
(define-values [y z] (foo)) 
+0

Espera, ¿estás diciendo que hay momentos en que la razón de la continuación es "desconocida" en el momento de su captura? Tal vez no estoy pensando lo suficiente sobre esto. –

+0

Sí, mira la nota al pie. A menos que quiera que cada una de estas continuaciones obtenga dinámicamente aries diferentes ... (Pero tengo que correr, así que no puedo dedicar más tiempo a esto ahora) –

+0

El enfoque dinámico era de hecho lo que tenía en mente cuando formulé la pregunta , pero tal vez no es viable. Debería intentar crear una prueba de concepto para ver si esto funcionaría. Mientras tanto, tiene un gran tic verde. Quiero decir, has esperado 2 meses por eso. :-) –

Cuestiones relacionadas