Frage

Ich versuche, eine Rücksperrsuche in Schema zu implementieren. Bisher habe ich Folgendes:

(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
)

Meine Funktionenzuweisungen und SELECT-U-PASS-Unit-Tests. Die Argumentzuordnung ist eine Hash-Tabelle mit (Make-hash), also sollte es in Ordnung sein.

Ich glaube, das Problem, das ich habe, hängt mit der Rückgabe von Falsch am Ende der Schleife zusammen, wenn kein rekursiver Wert einen Nicht-Falsewert zurückgibt (was eine gültige Zuordnung sein sollte). Gibt es ein Schema entspricht einer expliziten Rückgabeerklärung?

War es hilfreich?

Lösung

Die Antwort auf Ihre Frage lautet Jawohl:

(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
    )))

Dies setzt eine ein Ausfahrt Fortsetzung Damit Sie einen Ergebniswert aus dem Körper einer Funktion zurückgeben können. Der übliche Schema besteht darin, Ihr Rückgabeformular als das letzte Mal einzulegen, sodass sein Wert zurückgegeben wird:

    (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
)

Sie haben auch hier ein Problem:

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

Dieser Code tut nicht einen Anruf tätigen (assignment-complete n assignment). Vielmehr prüft es, ob eine Variable assignment-complete hat einen Nullwert, und wenn nicht, überprüft es assignment Variable, aber in jedem Fall wird sein zurückgegebener Wert sowieso nur ignoriert. Vielleicht fehlen dort noch einige Klammern und/oder eine else Klausel.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top