Qual é a diferença entre "set", "setq" e "setf" no Common Lisp?
common-lisp
Richard Hoskins
fonte
fonte
Respostas:
Originalmente, no Lisp, não havia variáveis lexicais - apenas dinâmicas. E não havia SETQ ou SETF, apenas a função SET.
O que agora está escrito como:
foi escrito como:
que foi abreviado para SETQ (SET Quoted):
Então as variáveis lexicais aconteceram, e o SETQ passou a ser usado para atribuição a elas também - portanto, não era mais um invólucro simples em torno do SET.
Mais tarde, alguém inventou o SETF (campo SET) como uma maneira genérica de atribuir valores a estruturas de dados, para espelhar os valores l de outras linguagens:
seria escrito como
Por simetria e generalidade, o SETF também forneceu a funcionalidade do SETQ. Nesse ponto, seria correto dizer que SETQ era uma primitiva de baixo nível e SETF uma operação de alto nível.
Então macros de símbolos aconteceram. Para que as macros de símbolo pudessem funcionar de forma transparente, percebeu-se que SETQ teria que agir como SETF se a "variável" atribuída a ela fosse realmente uma macro de símbolo:
Portanto, chegamos hoje: SET e SETQ são restos atrofiados de dialetos mais antigos e provavelmente serão inicializados por eventuais sucessores do Common Lisp.
fonte
f
realmente significa função , não campo (ou forma , para esse assunto) e fornece referências; portanto, embora o campo setf para faça algum sentido, parece que pode não estar correto.set
é uma função. Assim, ele não conhece o meio ambiente.set
não pode ver a variável lexical. Ele pode definir apenas o valor do símbolo de seu argumento.setq
não está mais "definido entre aspas". O fato desetq
ser uma forma especial, não uma macro mostra isso.fonte
(setq ls '(((1))))
,(setf (car (car (car ls))) 5)
é um comportamento indefinido, porque o valor dels
é constante (como modificar uma literal de cadeia de caracteres em C). Depois(setq ls (list (list (list 1))))
,(setf (car (car (car ls))) 5)
funciona exatamente comols->val->val->val = 5
em C.setq
é comoset
no primeiro argumento citado -(set 'foo '(bar baz))
é como(setq foo '(bar baz))
.setf
, por outro lado, é realmente sutil - é como um "indireto". Sugiro http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html como uma maneira melhor de começar entendê-lo do que qualquer resposta aqui pode dar ... em suma, no entanto,setf
leva a primeiro argumento como uma "referência", de modo que, por exemplo(aref myarray 3)
, funcione (como o primeiro argumentosetf
) para definir um item dentro de uma matriz.fonte
Você pode usar
setf
no lugar deset
ousetq
não vice-versa, poissetf
também pode definir o valor dos elementos individuais de uma variável se a variável tiver elementos individuais. Veja os exemplos abaixo:Todos os quatro exemplos atribuirão a lista (1, 2, 3) à variável denominada foo.
setf
tem a capacidade adicional de definir um membro da listafoo
para um novo valor.No entanto, você pode definir uma macro de símbolo que represente um único item dentro de
foo
Você pode usar
defvar
se você ainda não definiu a variável e não deseja atribuir um valor até mais tarde no seu código.fonte
Pode-se pensar
SET
eSETQ
ser construções de baixo nível.SET
pode definir o valor dos símbolos.SETQ
pode definir o valor das variáveis.Então
SETF
é uma macro, que fornece muitos tipos de configurações: símbolos, variáveis, elementos de matriz, slots de instância, ...Para símbolos e variáveis, pode-se pensar como se se
SETF
expandisse paraSET
eSETQ
.Portanto,
SET
eSETQ
são usados para implementar algumas das funcionalidades deSETF
, que é a construção mais geral. Algumas das outras respostas contam a história um pouco mais complexa, quando levamos em consideração as macros de símbolos.fonte
Gostaria de acrescentar às respostas anteriores que setf é macro que chama função específica dependendo do que foi passado como seu primeiro argumento. Compare os resultados da expansão macro de setf com diferentes tipos de argumentos:
Para alguns tipos de argumentos, a "função setf" será chamada:
fonte