O idioma que estou aprendendo é Scheme e estou trabalhando em um exercício que fornece isso:
(define (p) (p) )
(define (test x y) (if (= x 0)
0
y))
Em seguida, a pergunta pede para avaliar a expressão: (teste 0 (p)) e comentar sobre o comportamento que seria observado na avaliação de ordem normal e ordem de aplicação.
Estes são os meus pensamentos:
Sob ordem normal, o programa avaliaria as subexpressões antes de prosseguir:
Assim ( test 0 (p) )
se torna:
(test 0 p)
( if (= x 0) 0 p))
Saída de retorno 0
A única diferença na ordem do aplicativo seria que o programa fosse executado como:
( test 0 (p) )
torna-se:
(test 0 (p))
( if (= x 0) 0 (p)))
Saída de retorno 0
Assim (p)
, nunca seria avaliado, pois não será necessário.
Isso está correto? Informe-me, pois quase não tenho experiência em programação.
Respostas:
Que pesquisa você fez para responder a essa pergunta? Acabei de ligá-lo como está no Google e recebi como segunda resposta (a primeira pode ser tão boa que não chequei) uma referência a uma seção de uma bíblia sobre seu tópico: Estrutura de Hal Abelson, Jerry Sussman e Julie Sussman e Estrutura e Interpretação de programas de computador (MIT Press, 1984; ISBN 0-262-01077-1), também conhecido como livro dos feiticeiros. A referência é para a seção " Pedido normal e pedido aplicável ".
Afirma:
e acrescenta que o último é chamado avaliação preguiçosa .
Então você está com suas definições erradas e aceitando uma pela outra:
A ordem do aplicativo avalia subexpressões quando, ou seja, logo antes, o procedimento é aplicado.
a ordem normal passa as subexpressões como estão, sem avaliação, e prossegue com a avaliação somente quando o parâmetro formal correspondente deve realmente ser avaliado. (há uma reviravolta adicional em relação às questões ambientais ... mas é melhor esquecermos que, neste momento).
Além disso, você não entende adequadamente o mecanismo de chamada que envolve duas coisas:
o mecanismo de passagem de parâmetros, que inclui o processamento adequado dos argumentos reais da chamada, dependendo da regra de avaliação;
a "substituição" da chamada para a função pelo corpo da função (sem o cabeçalho).
No caso de avaliação de ordem aplicativa de
( test 0 (p) )
, você deve avaliar primeiro as sub-expressões do argumento. Estes são0
e(p)
.avaliação de um valor literal como
0
rendimento esse valor.o segundo argumento, no entanto, é uma chamada de procedimento para um procedimento sem parâmetro chamado
p
. Não possui parâmetro, para que não tenhamos preocupações com a ordem de avaliação. Então, para prosseguir com a avaliação, precisamos substituir a chamada pelo corpo do procedimento que segue a lista de argumentos e depois avaliar esse corpo. O corpo do procedimentop
, conforme definido na declaração(define (p) (p) )
, é(p)
para que fiquemos com a avaliação do que estávamos tentando avaliar. Em outras palavras, o processo de avaliação é capturado em um loop e não termina.... e você nunca consegue realmente concluir a chamada para a função
test
, pois a avaliação de seus argumentos não termina. Seu programa não termina.Esse risco de não rescisão, mesmo quando o argumento culpado nunca será usado na chamada, é um dos motivos para usar a avaliação normal da ordem, que pode ser um pouco mais difícil de implementar, mas pode ter melhores propriedades de rescisão.
Na avaliação de ordem normal , você não toca nas subexpressões de argumento. O que você faz é substituir a chamada
( test 0 (p) )
pelo corpo da funçãotest
, ou seja(if (= x 0) 0 y)
, onde os nomes dos argumentos (formais)x
ey
são substituídos pelos correspondentes argumentos reais0
e(p)
(até meio ambiente, ou renomear questões, que são importantes, mas que complicam a aqui, e são a principal diferença entre o Lisp original e a linguagem Scheme).Portanto, você substitui a avaliação de
( test 0 (p) )
pela avaliação de(if (= 0 0) 0 (p))
.Agora, a função
if
é uma função primitiva que geralmente sempre avalia seu primeiro argumento, mas avalia seus 2 últimos argumentos em ordem normal, avaliando apenas o útil, dependendo se o primeiro avalia como falso ou verdadeiro (atualmenteNIL
ou#f
por falsa , ou algum outro valor para true , no caso de Scheme - se minha memória não falhar). Como(= 0 0)
avalia como verdadeiro , a avaliação do valor condicional para avaliar o segundo argumento ainda não avaliado, ou seja0
, que sem surpresa (exceto no antigo Fortran) avalia0
.Respiração profunda.
fonte