Pergunta

Estou tentando implementar a pesquisa de rastreamento de retroilodínse no esquema. Até agora, eu tenho o seguinte:

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

Minhas funções atribuem-se a preenchimento e seleto-U Testes de unidade de passagem. A tarefa de argumento é uma tabela de hash com (Make-hash), por isso deve ficar bem.

Acredito que o problema que tenho está relacionado ao retorno falso no final do loop, se não houver retornar um valor não-false (que deve ser uma tarefa válida). Existe um esquema equivalente a uma declaração de devolução explícita?

Foi útil?

Solução

A resposta para sua pergunta é sim:

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

Isso configura um saída continuação para que você possa retornar um valor de resultado do corpo de uma função. O esquema usual é colocar seu formulário de retorno como o último, para que seu valor seja retornado:

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

Você também tem um problema aqui:

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

Este código faz não faça uma ligação (assignment-complete n assignment). Em vez disso, verifica se uma variável assignment-complete tem um valor não nulo e, se não, verifica assignment variável, mas, em qualquer caso, seu valor retornado é apenas ignorado de qualquer maneira. Talvez mais alguns parênteses estejam faltando lá, e/ou um else cláusula.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top