Pourquoi Clojure a-t-il des «mots-clés» en plus des «symboles»?

130

J'ai une connaissance passagère d'autres Lisps (en particulier Scheme) depuis longtemps. Récemment, j'ai lu sur Clojure . Je vois qu'il a à la fois des «symboles» et des «mots-clés». Symboles que je connais, mais pas les mots-clés.

D'autres Lisps ont-ils des mots-clés? En quoi les mots clés sont-ils différents des symboles autres que ceux ayant une notation différente (par exemple: deux points)?

Laurence Gonsalves
la source

Réponses:

139

Voici la documentation Clojure pour les mots-clés et les symboles.

Les mots-clés sont des identificateurs symboliques qui s'évaluent par eux-mêmes. Ils fournissent des tests d'égalité très rapides ...

Les symboles sont des identificateurs qui sont normalement utilisés pour désigner autre chose. Ils peuvent être utilisés dans les formulaires de programme pour faire référence aux paramètres de fonction, aux liaisons let, aux noms de classe et aux variables globales ...

Les mots-clés sont généralement utilisés comme des "chaînes constantes" légères, par exemple pour les clés d'une table de hachage ou les valeurs de distribution d'une méthode multiple. Les symboles sont généralement utilisés pour nommer des variables et des fonctions et il est moins courant de les manipuler directement en tant qu'objets, sauf dans les macros et autres. Mais rien ne vous empêche d'utiliser un symbole partout où vous utilisez un mot-clé (si cela ne vous dérange pas de les citer tout le temps).

Le moyen le plus simple de voir la différence est de lire Keyword.javaet Symbol.javadans la source Clojure. Il existe quelques différences de mise en œuvre évidentes. Par exemple, un symbole dans Clojure peut avoir des métadonnées et un mot-clé ne peut pas.

En plus de la syntaxe simple-deux-points, vous pouvez utiliser un double-virgule pour créer un mot-clé qualifié d'espace de nom.

user> :foo
:foo
user> ::foo
:user/foo

Common Lisp a des mots-clés, tout comme Ruby et d'autres langages. Ils sont bien sûr légèrement différents dans ces langues. Quelques différences entre les mots clés Common Lisp et les mots clés Clojure:

  1. Les mots clés dans Clojure ne sont pas des symboles.

    user> (symbol? :foo)  
    false
    
  2. Les mots clés n'appartiennent à aucun espace de noms, sauf si vous les qualifiez spécifiquement:

    user> (namespace :foo)
    nil
    user> (namespace ::foo)
    "user"
    

(Merci Rainer Joswig de m'avoir donné des idées de choses à examiner.)

Brian Carper
la source
10
Cela explique quelles sont les différences, mais pas pourquoi deux constructions différentes sont nécessaires. Clojure n'aurait-il pas pu créer quelque chose avec l'union des capacités des mots-clés et des symboles?
25
Les mots clés sont légers et ont une syntaxe pratique, je pense que c'est à peu près tout ce qu'il y a à faire. La langue fonctionnerait bien sans eux, mais ils sont agréables à avoir et ils sont très largement utilisés. Vous ne pouvez pas avoir une union de leurs capacités car les mots-clés sont toujours auto-évalués (c'est-à-dire que vous ne pouvez pas les utiliser comme noms de variables ou de fonctions) et les symboles en général ne peuvent pas toujours s'auto-évaluer.
Brian Carper
1
Il semble des mots - clés sont plus utiles que les clés dans hashmaps etc car ils ne changent pas une fois évalué: (eval (eval ':a))vs (eval (eval ''a)). Y a-t-il d'autres avantages? En termes de performances, ils sont identiques?
kristianlm
5
(identique?: qwe: qwe) -> true. (identique? 'qwe' qwe) -> false. Les symboles utilisent une chaîne interne, donc la comparaison est également rapide.
desudesudesu
29

Common Lisp a des symboles de mots clés.

Les mots clés sont également des symboles.

(symbolp ':foo) -> T

Ce qui rend les mots clés spéciaux:

  • : foo est analysé par le lecteur Common Lisp comme le mot clé symbol :: foo
  • les mots-clés s'évaluent d'eux-mêmes:: foo ->: foo
  • le package home des symboles de mots-clés est le package KEYWORD: keyword: foo ->: foo
  • les mots-clés sont exportés à partir du package KEYWORD
  • les mots clés sont des constantes, il n'est pas permis d'attribuer une valeur différente

Sinon, les mots-clés sont des symboles ordinaires. Ainsi, les mots clés peuvent nommer des fonctions ou avoir des listes de propriétés.

Rappelez-vous: en Common Lisp, les symboles appartiennent à un package. Cela peut être écrit comme suit:

  • foo, lorsque le symbole est accessible dans le package courant
  • foo: bar, lorsque le symbole FOO est exporté depuis le package BAR
  • foo :: bar, lorsque le symbole FOO est dans le package BAR

Pour les symboles de mots-clés, cela signifie que: foo, keyword: foo et keyword :: foo sont tous le même symbole. Ainsi, les deux dernières notations ne sont généralement pas utilisées.

Donc: foo est simplement analysé pour être dans le package KEYWORD, en supposant que ne pas donner de nom de package avant le nom du symbole signifie par défaut le package KEYWORD.

Rainer Joswig
la source
6

Les mots clés sont des symboles qui s'évaluent d'eux-mêmes, vous n'avez donc pas à vous rappeler de les citer.

Greg Hewgill
la source
5
Est-ce que c'est ça? Taper: plutôt que «ne semble pas être une grande victoire, d'autant plus que: est une pression supplémentaire sur la plupart des claviers.
Laurence Gonsalves
11
Eh bien, c'est plus que juste le personnage, vraiment. Les mots-clés restent des mots-clés après l'évaluation, tandis que les symboles sont évalués en fonction de ce à quoi ils sont liés. Cela ressemble plus à une différence sémantique, car ils sont généralement utilisés à des fins différentes.
Greg Hewgill
13
Les mots clés ne sont pas des symboles dans Clojure
David Plumpton
4

: les mots-clés sont également traités spécialement par de nombreuses collections, ce qui permet une syntaxe vraiment pratique.

(:user-id (get-users-map))

est le même que

((get-users-map) :user-id)

cela rend les choses un peu plus flexibles

Arthur Ulfeldt
la source
21
Ceci est également vrai pour les symboles, ('a {' a 1 'b 2}) => 1 et ({' a 1 'b 2}' b) => 2.
Jonas
4

Pour les mots-clés, les valeurs de hachage sont calculées et mises en cache lors de la première construction du mot-clé. Lorsque vous recherchez un mot clé en tant que clé de hachage, il renvoie simplement la valeur hachée précalculée. Pour les chaînes et les symboles, le hachage est recalculé à chaque recherche.

La raison pour laquelle les mêmes mots-clés nommés sont toujours identiques, ils contiennent leurs propres valeurs de hachage. Comme la recherche dans les cartes et les ensembles est faite à partir de clés de hachage, cela permet une meilleure efficacité de la recherche en cas de nombreuses recherches, pas dans la recherche elle-même.

Ivan Pierre
la source
0

Les mots clés sont globaux , les symboles ne le sont pas .

Cet exemple est écrit en JavaScript, mais j'espère qu'il aidera à faire passer le message.

const foo = Symbol.for(":foo") // this will create a keyword
const foo2 = Symbol.for(":foo") // this will return the same keyword
const foo3 = Symbol(":foo") // this will create a new symbol
foo === foo2 // true
foo2 === foo3 // false

Lorsque vous construisez un symbole à l'aide de la Symbolfonction, vous obtenez un symbole distinct / privé à chaque fois. Lorsque vous demandez un symbole via la Symbol.forfonction, vous récupérez à chaque fois le même symbole.

(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript

Ce sont tous les mêmes.


Les noms des arguments de fonction sont locaux. c'est-à-dire pas des mots-clés.

(def foo (fn [x] (println x))) ; x is a symbol
(def bar (fn [x] (println x))) ; not the same x (different symbol)
John Leidegren
la source