Quoting, symboles

Comprendre le quoting

Le quoting est un concept déroutant. Nous l’avons rencontré pour écrire des listes :

'(0 1 2 3 "Bonjour")

Il possède cependant une bizarrerie que n’a pas la fonction list :

guile> (list (+ 1 1) (+ 2 3))
(2 5)
guile> '((+ 1 1) (+ 2 3))
((+ 1 1) (+ 2 3))

Que se passe-t-il ?

Le quoting est en fait un moyen d’empêcher l’évaluation d’une expression. Il y a un lien entre la forme des expressions et la représentation des listes. Prenons l’expression :

(format #f "Bonjour ~a !" prénom)

Dans un programme, cette expression est évaluée comme un appel de la fonction format, qui renvoie une chaîne de caractères. Cependant, en rajoutant une apostrophe, on empêche l’évaluation.

guile> '(format #f "Bonjour ~a !" prénom)
(format #f "Bonjour ~a !" prénom)

On obtient alors l’expression sous forme d’une liste. Les éléments familiers de cette liste sont #f et "Bonjour ~a !", un booléen et une chaîne de caractères. On dit que les nombres, chaînes de caractères et booléens sont des objets auto-évaluateurs, car dans une expression, ils s’évaluent à eux-mêmes, comme on peut l’observer dans le bac à sable :

guile> "Bonjour ~a !"
"Bonjour ~a !"

Que sont les deux autres éléments de la liste, format et prénom ? Ce ne sont pas des chaînes de caractères, puisqu’ils sont affichés sans guillemets. On les appelle des symboles. Lorsque l’on écrit prénom dans l’expression, cela constitue un symbole. Simplement, les symboles, eux, ne sont pas auto-évaluateurs. Un symbole s’évalue à la valeur de variable dont il est le nom :

guile> (define prénom "Nathan")
guile> 'prénom
prénom
guile> prénom
"Nathan"

Les symboles sont d’usage si courant qu’ils sont familiers des LilyPondeurs :

\tag #'edition (
\override NoteHead.style = #'cross

L’apostrophe est un raccourci syntaxique pour quote. On peut donc écrire indifféremment

'(1 2.4 "Bonjour")

ou

(quote (1 2.4 "Bonjour"))

Quasiquotes

La syntaxe des quasiquotes permet d’évaluer des expressions tout de même au milieu d’une quote. Pour cela, il faut remplacer quote par quasiquote, et marquer les expressions à évaluer avec unquote.

guile> (quasiquote (0 1 2 (unquote (+ 1 2)) "Bonjour"))
(0 1 2 3 "Bonjour")

L’équivalent avec la syntaxe pratique est de remplacer l’apostrophe par un accent grave (backtick, le caractère `) et de marquer les expressions évaluées avec une virgule.

guile> `(0 1 2 ,(+ 1 2) "Bonjour")
(0 1 2 3 "Bonjour")

Cette syntaxe est courante pour créer des listes contenant des symboles. Ainsi, plutôt que

(define prénom "Nathan")
(list 'format #f "Bonjour ~a !" prénom)

on écrira en général

(define prénom "Nathan")
`(format #f "Bonjour ~a !" ,prénom)

Identité des symboles

À première vue, les symboles sont similaires aux chaînes de caractères. Pourtant, il existe une différence essentielle entre les deux. Lorsque l’on crée deux chaînes de caractères, même égales, de la mémoire est allouée pour chacune et elles vivent indépendamment l’une de l’autre. Au contraire, les symboles sont uniques. Un même symbole n’est jamais stocké deux fois. Lorsqu’apparaît un symbole déjà connu, il est réutilisé automatiquement, avec la même addresse en mémoire.

Pour le test equal?, il n’y a aucune différence, car equal? teste l’égalité structurelle d’objets. Pour des chaînes de caractères, equal? regardera si elles ont exactement les mêmes caractères. C’est un autre test, nommé eq?, qui détermine si deux objets ont la même addresse en mémoire, autrement dit, si deux objets sont en fait le même objet. Alors que equal? est un test d’égalité, eq? est un test d’identité.

guile> (equal? "bonjour" "bonjour")
#t
guile> (eq? "bonjour" "bonjour")
#f
guile> (equal? 'bonjour 'bonjour)
#t
guile> (eq? 'bonjour 'bonjour)
#t

L’intérêt de eq? est d’être très rapide. Il suffit de constater si oui ou non les deux objets ont la même adresse. Au contraire, un test equal? peut être coûteux en temps, et sera d’autant plus coûteux que les objets sont grands, comme de longues chaînes de caractères. Aussi, on retient que les symboles peuvent être comparés avec eq?, et qu’il est avantageux de les comparer toujours avec eq?.