Pergunta

Estou apenas começando a trabalhar no SICP (por conta própria; isso não é para uma aula), e tenho lutado com o Exercício 1.6 há alguns dias e eu simplesmente não consigo descobrir. Este é o que Alyssa redefina if em termos de cond, igual a:

(define (new-if predicate then-clause else-clause)
    (cond (predicate then-clause)
          (else else-clause))

Ela o testa com sucesso em alguns casos simples e depois o usa para reescrever o programa Square Root (que funcionou bem com if):

(define (sqrt-iter guess x)
    (new-if (good-enough? guess x)
            guess
            (sqrt-iter (improve guess x)
                       x)))

A pergunta então pergunta: "O que acontece quando Alyssa tenta usar isso para calcular raízes quadradas? Explique". [Se necessário, fico feliz em reproduzir os outros procedimentos (good-enough?, improve, etc.), apenas me avise.

Agora, eu sei o que acontece: ele nunca retorna um valor, o que significa que o programa recorre infinitamente. Eu simplesmente não consigo explicar por que isso acontece. Qualquer que seja a diferença sutil entre if e new-if está me iludindo. Todo e qualquer ajuda muito apreciado.

Foi útil?

Solução

new-if é uma função. Quando uma função é chamada, qual é a primeira coisa que o esquema faz com a lista de argumentos? Avalia tudo os argumentos.

Outras dicas

new-if é um procedimento e o esquema usa a avaliação de ordem de aplicação (1.1.5), portanto, mesmo antes de new-if é realmente realizado, ele tem que avaliar todos os argumentos primeiro, que são guess e (sqrt-iter (improve guess x) x). Você pode ver que o último argumento é uma recursão, que chama de um novo new-if Procedimento, é assim que ocorre o loop infinito.

O comum if não precisa avaliar seus argumentos primeiro, apenas siga o caminho, essa é a diferença entre if e new-if. :)

Primeiro de tudo, você tem que entenda a diferença entre avaliação de pedidos aplicativos e ordem normal. O LISP usa a ordem aplicativa, mas expressões condicionais são avaliadas não como funções normais (SICP Capítulo 1.1.6):

(if <predicate> <consequent> <alternative>)

Para avaliar uma expressão IF, o intérprete começa avaliando o <predicate> parte da expressão. Se o <predicate> avalia um valor verdadeiro, o intérprete avalia o <consequent> e retorna seu valor. Caso contrário, avalia o <alternative> e retorna seu valor.

Ex1.6. novo-se:

(define (new-if predicate then-clause else-clause)
     (cond (predicate then-clause)
                (else else-clause)))

Diferença com 'if -states': se as states se avaliam uma a uma de predicada -> consequente -> alternativa,

No entanto, o 'novo-if' precisa avaliar todos os parâmetros, também conhecidos como argumentos, no momento em que é chamado (que significa 'outra cláusula' é avaliado no início !!),

E assim isso causa um loop infinito quando algum desses parâmetros se chama para um loop iterativo

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