127 votes

Quand utiliser ' citation en Lisp

Après avoir fait à travers les principales parties d’un livre d’introduction Lisp, j’ai toujours ne comprenais pas ce que l’opérateur spécial (ou l’équivalent ) fonction accomplit, mais cela a été partout code Lisp que j’ai vu.

Que fait-elle ?

192voto

Mikael Jansson Points 3234

Réponse courte Contourner le défaut d'évaluation des règles et de ne pas évaluer l'expression (symbole ou s-exp), en passant le long de la fonction exactement comme tapé.

Réponse Longue: Par Défaut, La Règle D'Évaluation

Lorsque régulièrement (j'y viendrai plus tard) la fonction est appelée, tous les arguments passés sont évalués. Cela signifie que vous pouvez écrire ceci:

(* (+ a 2)
   3)

Qui évalue (+ a 2), en évaluant a et 2. La valeur du symbole a est recherché dans le courant variable de liaison, puis remplacé. Dire a est actuellement lié à la valeur 3:

(let ((a 3))
  (* (+ a 2)
     3))

Nous aurions (+ 3 2), + est alors invoquée sur 3 et 2 ce qui donne 5. A l'origine, notre formulaire est désormais (* 5 3) de rendement de 15.

Expliquez - quote Déjà!

Alright. Comme vu ci-dessus, tous les arguments d'une fonction sont évalués, donc si vous voulez passer le symbole a , et non de sa valeur, vous ne voulez pas de l'évaluer. Lisp symboles de double les deux car leurs valeurs, et des marqueurs où vous dans d'autres langues auraient utilisé des chaînes, telles que les touches de tables de hachage.

C'est là que quote . Dites que vous voulez tracer les allocations de ressources à partir d'une application en Python, mais plutôt faire le traçage en Lisp. Votre application Python faire quelque chose comme ceci:

print "'("
while allocating:
    if random.random() > 0.5:
        print "(allocate %d)" random.randint(0, 20)
    else:
        print "(free %d)" % random.randint(0, 20)
    ...
print ")"

Vous donnant de sortie qui ressemble à ceci (un peu prettyfied):

'((allocate 3)
  (allocate 7)
  (free 14)
  (allocate 19)
  ...)

Rappelez-vous ce que j'ai dit à propos de quote ("tick") provoquant la règle par défaut de ne pas appliquer? Bon. Ce qui serait autrement arriver, c'est que les valeurs de allocate et free sont regardé en haut, et nous ne voulons pas que. Dans notre Lisp, nous souhaitons faire:

(dolist (entry allocation-log)
  (case (first entry)
    (allocate (plot-allocation (second entry)))
    (free (plot-free (second entry)))))

Pour que les données ci-dessus, la séquence suivante d'appels de fonction aurait été faite:

(plot-allocation 3)
(plot-allocation 7)
(plot-free 14)
(plot-allocation 19)

Mais Qu' list?

Eh bien, parfois, vous ne voulez évaluer les arguments. Disons que vous avez une chouette fonction de la manipulation d'un nombre et une chaîne et en retournant une liste de la résultante des ... choses. Nous allons faire un faux départ:

(defun mess-with (number string)
  '(value-of-number (1+ number) something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER (1+ NUMBER) SOMETHING-WITH-STRING (LENGTH STRING))

Hey! Ce n'est pas ce que nous voulions. Nous voulons sélectivement à évaluer certains arguments, et laisser les autres comme des symboles. Essayez le #2!

(defun mess-with (number string)
  (list 'value-of-number (1+ number) 'something-with-string (length string)))

Lisp> (mess-with 20 "foo")
(VALUE-OF-NUMBER 21 SOMETHING-WITH-STRING 3)

Pas Seulement quote, Mais backquote

Beaucoup mieux! Incidemment, ce modèle est tellement commun dans (la plupart) des macros, qu'il y a une syntaxe spéciale pour le faire. Le backquote:

(defun mess-with (number string)
  `(value-of-number ,(1+ number) something-with-string ,(length string)))

C'est comme utiliser quote, mais avec l'option explicitement à évaluer certains arguments en les préfixant avec des virgules. Le résultat est équivalent à l'utilisation de list, mais si vous êtes de la génération de code à partir d'une macro-vous souvent seulement à évaluer, sur des petites parties du code retourné, de sorte que le backquote est plus adapté. Pour de courtes listes, list peut être plus lisible.

Hey, Vous Avez Oublié quote!

Alors, où sommes-nous? Ah oui, qu'est - quote ? Il retourne son argument(s) non évaluée! Rappelez-vous ce que j'ai dit au début sur les fonctions? S'avère que certains opérateurs/fonctions doivent pas évaluer leurs arguments. Comme SI l'option -- vous ne voudriez pas que la branche else être évalué si il n'était pas pris, non? Soi-disant opérateurs spéciaux, en collaboration avec des macros, comme ça. Opérateurs spéciaux sont aussi les "axiome" de la langue -- ensemble minimal de règles -- sur lequel vous pouvez mettre en place le reste de Lisp en les combinant entre eux de différentes façons.

Retour à l' quote, si:

Lisp> (quote spiffy-symbol)
SPIFFY-SYMBOL

Lisp> 'spiffy-symbol ; ' is just a shorthand ("reader macro"), as shown above
SPIFFY-SYMBOL

Comparer (sur Acier-Banque Common Lisp):

Lisp> spiffy-symbol
debugger invoked on a UNBOUND-VARIABLE in thread #<THREAD "initial thread" RUNNING   {A69F6A9}>:
  The variable SPIFFY-SYMBOL is unbound.

Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(SB-INT:SIMPLE-EVAL-IN-LEXENV SPIFFY-SYMBOL #<NULL-LEXENV>)
0]

Car il n'y a pas d' spiffy-symbol dans le champ d'application actuel!

Résumé

quote, backquote (avec virgule), et list sont certains des outils que vous utilisez pour créer des listes, qui ne sont pas seulement des listes de valeurs, mais comme vous l'avez vu peut être utilisé comme léger (pas besoin de définir un struct) des structures de données!

Si vous souhaitez en savoir plus, je vous recommande de Peter Seibel livre Pratique Common Lisp pour une approche pratique pour l'apprentissage de Lisp, si vous êtes déjà dans la programmation en général. Finalement, sur votre Lisp voyage, vous allez commencer à utiliser des paquets trop. Ron Garret est L'Idiot du Guide de la Common Lisp Paquets vont vous donner une bonne explication de ceux-ci.

Happy hacking!

57voto

Adam Rosenfield Points 176408

Il est dit « n’évaluer moi ». Par exemple, si vous souhaitez utiliser une liste sous forme de données et non pas comme le code, vous mettriez un devis en face d’elle. Par exemple,

imprime "(+ 3 4) », tandis que imprime « 7 »

19voto

Xanthir Points 7035

D'autres personnes ont répondu à cette question de façon admirable, et Matthias Benkard apporte un excellent avertissement.

NE PAS UTILISER DE DEVIS POUR CRÉER DES LISTES QUE VOUS POURREZ MODIFIER ULTÉRIEUREMENT. La spécification permet au compilateur de traiter la cité des listes comme des constantes. Souvent, un compilateur d'optimiser les constantes par la création d'une seule valeur pour eux dans la mémoire, puis de référencement que seule la valeur de tous les endroits où la constante apparaît. En d'autres termes, il peut traiter la constante comme un anonyme variable globale.

Cela peut causer des problèmes évidents. Si vous modifiez une constante, il peut très bien modifier d'autres utilisations de la même constante dans absolument aucun rapport avec le code. Par exemple, vous pouvez comparer une variable à '(1 1) dans une fonction, et dans un tout autre fonction, démarrer une liste avec '(1 1) et ensuite d'ajouter plus de choses. Lors de l'exécution de ces fonctions, vous pouvez trouver que la première fonction ne correspond pas à des choses plus correctement, parce que c'est maintenant d'essayer de comparer la variable à '(1 1 2 3 5 8 13), qui est ce que la deuxième fonction renvoyée. Ces deux fonctions sont complètement indépendants, mais ils ont un effet sur les autres en raison de l'utilisation de constantes. Même les plus folles mauvais effets peuvent se produire, comme tout à fait normal, liste itération soudain boucle infinie.

Utiliser devis lorsque vous avez besoin d'une liste de constantes, telles que des fins de comparaison. Utilisation de la liste quand vous allez modifier le résultat.

14voto

Matthias Benkard Points 11264

Une réponse à cette question, dit que la CITATION "crée la liste des structures de données". Ce n'est pas tout à fait droit. La CITATION est plus fondamental que cela. En fait, la CITATION est trivial de l'opérateur: Son but est d' empêcher quelque chose de se produire. En particulier, il ne crée rien.

Ce que (CITATION X) dit que c'est en gros "ne rien faire, juste me donner X." X n'a pas besoin d'être une liste comme dans (QUOTE (A B C)) ou un symbole, comme dans (DEVIS FOO). Il peut être n'importe quel objet quelle que soit. En effet, le résultat de l'évaluation de la liste qui est produit par (LISTE de CITER QUELQUES-OBJET) sera toujours juste de retour de QUELQUES-OBJET, quel qu'il soit.

Maintenant, la raison pour laquelle (QUOTE (A B C)) semble comme si elle a créé une liste dont les éléments sont A, B, et C, est qu'une telle liste est vraiment de quoi il en retourne; mais au moment où le formulaire de soumission est évaluée, la liste a généralement déjà été en existence pendant un certain temps (comme une composante de la forme de CITATION!), créés soit par le chargeur ou le lecteur avant l'exécution du code.

L'une des conséquences de ce qui tend à faire trébucher les débutants assez souvent, c'est qu'il est très déconseillé de modifier une liste retournée par un formulaire de demande de DEVIS. Les données renvoyées par la CITATION est, pour toutes fins utiles, être considérés comme faisant partie du code en cours d'exécution et doit donc être considérée comme étant en lecture seule!

11voto

Kyle Burton Points 10471

La citation empêche l'exécution ou l'évaluation d'un formulaire, le tournant de la place dans les données. En général, vous pouvez exécuter les données par eval avec elle.

devis crée la liste des structures de données, par exemple, les suivantes sont équivalentes:

(quote a)
'a

Il peut également être utilisé pour créer des listes (ou les arbres):

(quote (1 2 3))
'(1 2 3)

Vous êtes probablement mieux d'obtenir un introductary livre sur le langage lisp, comme la Pratique Common Lisp (qui est disponible à la lecture en ligne).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X