Ah, contains?
... supposément l'une des cinq premières questions fréquemment posées concernant Clojure.
Cela ne vérifie pas si une collection contient une valeur; cela vérifie si un élément pourrait être récupéré avec get
ou, en d'autres termes, si une collection contient une clé. Cela a du sens pour les ensembles (qui peuvent être considérés comme ne faisant aucune distinction entre clés et valeurs), les maps (donc (contains? {:foo 1} :foo)
est true
) et les vecteurs (mais notez que (contains? [:foo :bar] 0)
est true
, car les clés ici sont des indices et le vecteur en question contient l'index 0
!).
Pour ajouter à la confusion, dans les cas où il n'a pas de sens d'appeler contains?
, il renvoie simplement false
; c'est ce qui se passe dans (contains? :foo 1)
et aussi (contains? '(100 101 102) 101)
. Mise à jour: Dans Clojure ≥ 1.5 contains?
lève une erreur lorsqu'il reçoit un objet d'un type qui ne supporte pas le test de "membership" de la clé prévu.
La manière correcte de faire ce que vous essayez de faire est la suivante:
; la plupart du temps cela fonctionne
(some #{101} '(100 101 102))
Lorsque vous cherchez l'un des éléments d'un ensemble, vous pouvez utiliser un ensemble plus grand; lorsque vous cherchez false
/ nil
, vous pouvez utiliser false?
/ nil?
-- car (#{x} x)
renvoie x
, donc (#{nil} nil)
est nil
; lorsque vous cherchez l'un des éléments multiples dont certains peuvent être false
ou nil
, vous pouvez utiliser
(some (zipmap [...les éléments...] (repeat true)) la-collection)
(Notez que les éléments peuvent être passés à zipmap
dans n'importe quel type de collection.)
7 votes
Il est vrai que la fonction contains? est étrange dans Clojure :) On espère que Clojure 1.3 la renommera en contains-key? ou quelque chose de similaire.
4 votes
Je pense que cela a été discuté à plusieurs reprises maintenant. Le contient? ne changera pas. Voir ici: groups.google.com/group/clojure/msg/f2585c149cd0465d et groups.google.com/group/clojure/msg/985478420223ecdf
1 votes
@kotarak merci pour le lien! Je suis en fait d'accord avec Rich ici en ce qui concerne l'utilisation du nom contains? bien que je pense qu'il devrait être modifié pour générer une erreur lorsqu'il est appliqué à une liste ou une séquence