Actuellement en train d'apprendre le lisp commun, suivant Practical Common Lisp de Peter Seibel (je suis au chapitre 11, sur les collections), j'ai des difficultés à comprendre comment fonctionne setf
derrière le capot.Comment fonctionne setf sous le capot?
Compte tenu de cette expression:
(setf a 10)
avoir bien compris comment l'interprète peut (1) récupérer la variable nommée a
, et (2) modifier la valeur il pointe à 10
.
Maintenant, dans le cas de collections particulières, par exemple des listes, des vecteurs ou des tables de hachage, setf peut également être utilisé pour modifier les valeurs contenues dans la collection. Par exemple, avec un vecteur:
(defparameter *x* '(a b c d))
(setf (elt *x* 1) bb)
Cela me rend méfiant au sujet setf
, car il est éventuellement trouver des informations non accessibles trivialement, ou de faire de la magie noire. Je vois plusieurs possibilités.
1. setf est une fonction
L'expression (elt *x* 1)
revient 'b
, donc setf
travaille pratiquement avec (setf b bb)
. Je ne comprends pas alors comment setf
peut déduire quel objet (ici, la liste *x*
) il doit modifier, sans avoir la valeur de retour de elt
contenant à la fois une indication qu'il provient d'une collection, et un pointeur sur ladite collection. Cela semble compliqué.
2. setf est une macro
L'idée est, comme setf
est une macro, il travaille directement avec le (setf (elt *x* 1) bb)
et peut donc extraire la partie elt *x* 1
à déduire quel objet/collection est utilisé, et doit donc être modifié.
Il ne semble pas très efficace, ni fiable, ni résistant aux opérations complexes. Cependant, depuis que je suis incapable d'exécuter ce code:
(funcall (find-symbol (concatenate 'string "E" "LT")) *x* 1) ; -> B
(setf (funcall (find-symbol (concatenate 'string "E" "LT")) *x* 1) 'bb) ; -> ERROR : (SETF FUNCALL) is only defined for functions of the form #'symbol
Cela me font penser que setf
est une macro mettant en œuvre une heuristique très simple pour récupérer la fonction à appeler, et toutes les autres informations nécessaires. Cela semble compliqué.
3. setf est un cas particulier d'interprétation
Une autre façon d'aller pourrait être d'avoir setf être traitée différemment par l'interprète lui-même, face à la magie noire pour mettre en œuvre correctement le comportement attendu. Cela semble compliqué.
4. il y a quelque chose que je ne sais pas Lisp
Probablement la vraie réponse. Qu'est-ce que j'ai raté ?
Question supplémentaire: la méthode d'implémentation dépend-elle de la mise en œuvre de l'interpréteur Lisp? (ou, plus simplement, ce que définit exactement la norme Lisp commune à propos de l'implémentation de setf) J'utilise actuellement clisp mais des informations sur d'autres implémentations sont les bienvenues.
Le hyperspec a des détails sur 'SETF'/endroits [5.1 Référence Généralisée] (http://www.lispworks.com/documentation/HyperSpec/Body/05_a.htm), bien qu'il soit assez technique. – jkiiski