Pergunta

Esta passagem de On Lisp é genuinamente confuso - não está claro como retornar uma lista citada como '(oh my) pode realmente alterar como a função se comporta no futuro:a lista retornada não será gerada novamente na função do zero, na próxima vez que for chamada?

Se definirmos exclamar para que seu valor de retorno incorpore uma lista citada,

(defun exclaim (expression) 
  (append expression ’(oh my)))

Então, qualquer modificação destrutiva posterior do valor de retorno

(exclaim ’(lions and tigers and bears)) 
->  (LIONS AND TIGERS AND BEARS OH MY)
(nconc * ’(goodness))
->  (LIONS AND TIGERS AND BEARS OH MY GOODNESS)

poderia alterar a lista dentro da função:

(exclaim ’(fixnums and bignums and floats)) 
->  (FIXNUMS AND BIGNUMS AND FLOATS OH MY GOODNESS)

Para fazer prova exclamativa contra tais problemas, deve ser escrito:

(defun exclaim (expression)
  (append expression (list ’oh ’my)))

Como exatamente é essa última chamada para exclaim adicionando a palavra goodness para o resultado?A função não está referenciando nenhuma variável externa, então como foi feita a chamada separada para nconc realmente alterar a forma como o exclaim função funciona?

Foi útil?

Solução

a) os efeitos da modificação literal listas é indefinido no padrão Common Lisp.O que você vê aqui como exemplo é um comportamento possível.

(1 2 3 4) é uma lista literal.Mas uma chamada para LIST como em (list 1 2 3 4) retorna uma lista recém-consutada em tempo de execução.

b) a lista são dados literais no código da função.Cada chamada retornará exatamente este objeto de dados.Se quiser fornecer uma lista nova em cada chamada, você precisará usar algo como LIST ou COPY-LIST.

c) Como a lista retornada é sempre o mesmo objeto de dados literal, modificá-la PODE ter o efeito descrito.Pode-se imaginar também que ocorre um erro se o código e seus objetos forem alocados em uma memória somente leitura.Modificar a lista tentaria gravar na memória somente leitura.

d) Uma coisa a ter em mente ao trabalhar com dados de lista literal no código-fonte é o seguinte:o compilador Lisp é gratuito para otimizar o armazenamento.Se uma lista aparecer várias vezes no código-fonte, um compilador poderá detectar isso e criar apenas UMA lista.Todos os vários lugares apontariam então para esta lista.Assim, a modificação da lista teria o efeito de que estas alterações poderiam ser visíveis em vários locais.

Isso também pode acontecer com outros objetos de dados literais, como matrizes/vetores.

Se a sua estrutura de dados faz parte do código, você retorna essa estrutura de dados interna, modifica essa estrutura de dados - então tenta modificar seu código.

Observe também que Lisp pode ser executado por um intérprete.O interpretador normalmente funciona na estrutura de origem Lisp - o código não é código de máquina, mas código Lisp interpretado como dados Lisp.Aqui você poderá modificar o código-fonte em tempo de execução, não apenas os dados incorporados no código-fonte.

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