Pregunta

Estoy tratando de averiguar cómo puedo hacer un "pronto retorno" en un procedimiento esquema de sin utilizando un if de nivel superior o cond como constructo.

(define (win b)
 (let* ((test (first (first b)))
        (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                       (enumerate (length b)))))
  (when (and (not (= test 0)) result) test))
 0)

Por ejemplo, en el código anterior, quiero win para volver test si se cumple la condición when, en caso contrario devuelve 0. Sin embargo, lo que sucede es que el procedimiento siempre de retorno 0, independientemente de el resultado de la condición when.

La razón por la que estoy estructurando mi código de esta manera es porque en este procedimiento que necesito hacer numerosos controles complejos (múltiples bloques similares a la let* en el ejemplo) y poner todo en una gran cond sería muy difícil de manejar.

¿Fue útil?

Solución

Aquí es cómo utilizar llamada / cc para construir return mismo.

(define (example x)
  (call/cc (lambda (return)
    (when (< x 0) (return #f))
    ; more code, including possible more calls to return
    0)))

Algunos esquemas definen una macro llamada Let / cc que le deja caer algunos de los ruidos de la lambda:

(define (example x)
  (let/cc return
    (when (< x 0) (return #f))
    0))

Por supuesto, si el esquema no, vamos / cc es trivial para escribir.


Esto funciona porque llamada / cc guarda el punto en el que fue llamado como una continuación. Se pasa que la continuación a su argumento de la función. Cuando la función se llama a que la continuación, Esquema abandona cualquier pila de llamadas que se había acumulado hasta ahora y continúa desde el final de la llamada llamada / cc. Por supuesto, si la función nunca llama la continuación, entonces, sólo se devuelve normalmente.

Las continuaciones no consiguen verdaderamente endiablada hasta que empiece a devolverlos a esa función, o tal vez de almacenarlos en una estructura de datos global y llamar más tarde. De lo contrario, ellos son como declaraciones estructuradas-goto de cualquier otro idioma (mientras / para / pausa / retorno / continuar / excepciones / condiciones).


No sé cuál es su código completo se parece, pero podría ser mejor ir con la cond y para factorizar los complejos controles en funciones separadas. Necesitando return y let* suele ser un síntoma de código excesivamente imperativa. Sin embargo, el método de llamada / cc debe obtener su código de trabajo por ahora.

Otros consejos

Una forma sería utilizar la recursividad en lugar de bucle, a continuación, una salida temprana se logra de manera recursiva no más.

Puede utilizar el soporte "llamar con la continuación actual" para simular un retorno. Hay un ejemplo en Wikipedia . La función se llama llamar-con-corriente de continuación , aunque a menudo hay un alias llamado llamar / cc , que es exactamente lo mismo. También hay un ejemplo un poco más limpio aquí

Nota: Esta es una técnica bastante avanzada y programación Scheme puede ser un poco la mente de flexión en un primer momento !!!! ...

En este caso, usted no quiere un cuándo, si quieres una, aunque no de nivel superior.

(define (win b)
  (let* ((test (first (first b)))
         (result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
                        (enumerate (length b)))))
    (if (and (not (= test 0)) result) 
        test
        0)))

La razón por la que siempre regresaba a cero es que si el cuerpo del ejecutado cuando se consiguió, su resultado se dejó caer en el suelo. Usted ve, el lambda implícita en la función de definir la forma implícita crea un bloque BEGIN también, así

(define foo 
  (lambda (b)
     (begin
       (let ...)
       0)))

y la forma en iniciar las obras es que se devuelve el resultado de la última forma en el interior, mientras que dejar caer todos los resultados intermedios en el suelo. Esos resultados intermedios están destinados a tener efectos secundarios. Usted no está usando alguna de que, lo que es grande (!), Pero hay que tener cuidado de que sólo tienen una forma (cuyo resultado realmente desea) dentro de la definición de la función.

Grem

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top