2012-06-19 19 views
8

Algunas preguntas aquí, con respecto a letcc que se utiliza en The Seasoned Schemer.The Seasoned Schemer, letcc y astucia

(define (intersect-all sets) 
    (letcc hop 
    (letrec 
     ((A (lambda (sets) 
      (cond 
       ((null? (car sets)) (hop '()) 
       ((null? (cdr sets)) (car sets)) 
       (else 
       (intersect (car sets) 
          (A (cdr sets))))))) 
     ; definition of intersect removed for brevity 
     (cond 
     ((null? sets) '()) 
     (else (A sets)))))) 
  1. creo que entiendo lo letcc se consiga, y que es, básicamente, algo así como catch y throw en Ruby (y aparentemente CL), que básicamente significa todo un bloque de código puede ser interrumpida por llamar a cualquier el nombre letcc es. Esto se siente como la cosa menos "funcional" que he encontrado en esta pequeña serie de libros y me hace sentir un poco indeciso de usarlo, ya que quiero aprender un buen estilo funcional. ¿Acabo de malinterpretar letcc, o no es realmente un concepto de programación funcional y solo existe para mejorar el rendimiento? La idea de que puedo estar en el medio de una rutina y de repente llegar a otro punto del código me parece un poco incorrecta ... como abusar de try/catch en Java para el flujo del programa.

  2. letcc no parece existir en la versión de guile (1.8.7) que he instalado en OS X. ¿Hay otro nombre para el que debería estar buscando en astucia?

  3. Si estoy malentendido letcc comparándolo con try/catch en Java, o la captura/tirar rubí (que es no manejo de excepciones, para ser claros, para los no Rubyistas), ¿cómo es exactamente funciona, a nivel funcional? ¿Se puede expresar de una manera más larga y compleja que me convence de que es funcional después de todo?

+1

Si tiene una implementación que admita ambas continuaciones "normales" y escape de continuación, normalmente es más barato usar esta última. El patrón en su ejemplo es un ajuste natural para las continuaciones de escape. La abreviatura estándar es 'let/ec'. – soegaard

+0

FYI, [esta página] (http://community.schemewiki.org/?seasoned-schemer) muestra cómo definir 'letcc' en términos de' call/cc' utilizando una macro simple. –

+0

@JonO, lo leí antes y lo intenté, pero engaño solo dice 'ERROR: sintaxis inválida()' 'ABORT: (misc-error)'. Comprobé que lo hice como dice la página, pero todavía no funciona. Probablemente descubriré por qué cuando llegue a aprender macros. – d11wtq

Respuesta

11
  1. "funcional" tiene varios significados, pero sin significado populares continuaciones contradice de ninguna manera. Pero pueden pueden ser utilizados para crear código que es difícil de leer. No son herramientas que pueden ser "abusadas para el flujo del programa": son herramientas de flujo de programa.

  2. No te puedo ayudar allí. Sé que hubo semi-recientes en las continuaciones en Guile, pero no sé dónde están las cosas. Definitivamente debería tener call-with-current-continuation, generalmente también bajo el nombre más descriptivo de call/cc, y let/cc es una macro simple que puede compilarse con call/cc.

    lo que puedo decir que, en la raqueta hay una orden interna let/cc junto con un montón de others builtins en el same family, y, además, hay un whole library de varios operadores de control (con una extensa lista de referencias.).

  3. Los usos simples de let/cc son de hecho similares a un tipo de atrapar/lanzar - más específicamente, tales continuaciones se conocen comúnmente como "continuación de escape" (o algunas veces "hacia arriba"). Este es el tipo de uso que tiene en ese código, y que a menudo se utiliza para implementar un abort o un return.

    Pero las continuaciones en Scheme son cosas que pueden usarse en cualquier lugar.Para un ejemplo muy simple que muestra esta diferencia, intente esto:

    (define (foo f) (f 100)) 
    (let/cc k (+ (foo k) "junk") (more junk)) 
    
  4. Por último, si desea obtener más información sobre las continuaciones, se puede ver las partes pertinentes de PLAI, también hay una mayor brief by-example overview que Mateo Podría escribió , y puede ver algunos class notes que escribí que están basados ​​en PLAI, con algunos ejemplos que se inspiraron en la última publicación.

+2

Wow, después de leer ese artículo de Matthew Right mi opinión ha cambiado Creo que realmente entender cómo funciona 'call/cc' hace que parezca mucho más limpio de lo que pensaba originalmente. Enormes gracias por la explicación. Resulta que mi versión de Guile tiene 'call/cc' y' call-with-current-continuation', pero no 'letcc'. Además, 'call/cc' es mucho más interesante que' catch/throw' en ruby, ya que te permite hacer cosas mucho más geniales. Supongo que The Seasoned Schemer explorará esto con más detalle en capítulos posteriores. – d11wtq

+0

Si ha terminado con su texto, eche un vistazo a mis notas de clase también: hay varios ejemplos que están mucho más extendidos, con un desarrollo completo de generadores y amb, y comienza con una descripción de CPS: el forma de implementar algunos de estos en otros idiomas. –

+4

Y, por cierto, su nombre es Matthew Might. (Puede que tenga razón, pero su nombre es Poder.) –