Domanda

Sto cercando di implementare la ricerca di back-tracking nello schema. Finora ho quanto segue:

(define (backtrack n graph assignment)  
    (cond (assignment-complete n assignment) (assignment) )

    (define u (select-u graph assignment))

    (define c 1)
    (define result 0)

    (let forLoop ()
        (when (valid-choice graph assignment c)
             (hash-set! assignment u c)

             (set! result (backtrack n graph assignment))

             (cond ((not (eq? result #f)) result))

             (hash-remove! assignment u)            
        )

        (set! c (+ c 1))
        (when (>= n c) (forLoop))
    )

   #f ; I believe this is where I'm having problems
)

My Funzioni Test di assegnazione di assegnazione e Select-U Pass. L'assegnazione dell'argomento è un tasso di hash con (make-hash), quindi dovrebbe andare bene.

Credo che il problema che ho sia legato alla restituzione di falsi alla fine del ciclo, se nessun restituzione ricorsiva un valore non falso (che dovrebbe essere un incarico valido). Esiste uno schema equivalente a una dichiarazione di ritorno esplicita?

È stato utile?

Soluzione

La risposta alla tua domanda è :

(define (foo ...)
  (call-with-current-continuation
    (lambda (return)
      ...... ; here anywhere inside any sub-expression 
      ...... ; you can call (return 42)
      ...... ; to return 42 from `foo` right away
    )))

Questo crea un Uscita continuazione in modo da poter restituire un valore di risultato dall'interno del corpo di una funzione. Il solito schema è quello di mettere il modulo di ritorno come ultimo, quindi il suo valore viene restituito:

    (let forLoop ()
        (when (valid-choice graph assignment c)
             (hash-set! assignment u c)
             (set! result (backtrack n graph assignment))
             (cond
                 ((not (eq? result #f))
                   result))       ; the value of `cond` form is ignored
             (hash-remove! assignment u))
                                  ; the value of `when` form is ignored
        (set! c (+ c 1))
        (if (>= n c)     ; `if` must be the last form 
           (forLoop)     ; so that `forLoop` is tail-recursive
           ;; else:
           return-value) ; <<------ the last form's value 
    )                    ; is returned from `let` form

   ;; (let forLoop ...) must be the last form in your function
   ;;                   so its value is returned from the function
)

Hai anche un problema qui:

(cond (assignment-complete n assignment) (assignment) )

Questo codice lo fa non effettuare una chiamata (assignment-complete n assignment). Piuttosto, controlla se una variabile assignment-complete ha un valore non nullo e, in caso contrario, controlla assignment variabile, ma in ogni caso il suo valore restituito viene comunque ignorato. Forse ci mancano altre parentesi lì e/o un else clausola.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top