2

In Clojure, (= [:a :b] (list :a :b)) return true, but (= [:a :b] (:a :b)) return false. Why?

I think that (list :a :b) is (:a :b), so all should not return true.

thinkerou
  • 1,781
  • 5
  • 17
  • 28

2 Answers2

7

(f x) asks to call function f with argument x. So, (:a :b) calls :a as a function, with :b as its argument. What that actually does is not terribly important at the moment, but it certainly doesn't return the list (:a :b) in the way that (list :a :b) does. If you want to treat a list as a data structure rather than as a function call, you can quote it, via (quote (:a :b)). To get more details on what quoting is all about, you can read When to use 'quote in Lisp - it's not Clojure-specific, but still relevant.

Community
  • 1
  • 1
amalloy
  • 89,153
  • 8
  • 140
  • 205
  • thanks a lot! I'm confused is that `(= '[:a :b] '(:a :b))` returns `true`, because one is list, another is vector. Okay, I should look "When to use 'quote in Lisp" first. – thinkerou Dec 14 '13 at 02:32
  • 1
    "Equality ... compares numbers and collections in a type-independent manner." http://clojuredocs.org/clojure_core/clojure.core/= – Diego Basch Dec 14 '13 at 07:25
  • Just to add to what's already implicit in what amalloy and Diego Basch said: ThinkerOu, you are experiencing two bits of flexibility in Clojure. (This flexibility is extremely useful, even though it means you have to be careful that the flexiblity doesn't hide bugs.) First, sequences of different kinds are often, in effect, automatically coerced to other sequence types. Second, keywords are often used as keys in Clojure `maps`, and because of this they can be treated as functions. (There's more to that last point.) That's how I think about it, though I'm also new to Clojure. – Mars Dec 14 '13 at 20:08
  • @Mars I think this comment is helpful on the whole, but automatic coercion of sequence types is a bit misleading. Collections are often implicitly `seq`'d, but (a) I don't know that I'd call this coercion, and (b) it isn't actually happening in his example. – amalloy Dec 14 '13 at 21:33
  • Thanks @amalloy. I thought that my way of putting it might be incorrect. – Mars Dec 15 '13 at 04:11
0

From The Joy Of Clojure 2nd Edition:

The identical? function in Clojure only ever returns true when the symbols are in fact the same object:

(let [x (with-meta 'goat {:ornery true})
      y (with-meta 'goat {:ornery false})]
  [(= x y)
   (identical? x y)
   (meta x)
   (meta y)])
;=> [true false {:ornery true} {:ornery false}]

Equals (=) compares contents of objects (without comparing meta-data, as shown above), identical? only true if they are the same object:

(let [x 'goat, y x]
  (identical? x y))
;=> true
Mark Fisher
  • 9,838
  • 3
  • 32
  • 38
  • I think the addition of the metadata might leave the fundamental point less clear than it might be. Another illustration: `(identical? [1 2 3] [1 2 3])` => `false` because the first and second vectors are two different data structures, constructed separately. – Mars Dec 14 '13 at 20:02
  • fair point, but i was trying to bring in a relevant quoted reference along the same lines. – Mark Fisher Dec 14 '13 at 22:50