Clojure

contains? is broken for vectors

Details

• Type: Defect
• Status: Closed
• Priority: Critical
• Resolution: Declined
• Affects Version/s: Release 1.3
• Fix Version/s: None
• Component/s: None
• Labels:
None
• Environment:
OSX Lion

Description

contains? returns the wrong result for the last item in a vector:

user> (map #(contains? [1 2 3 4] %) [1 2 3 4])
(true true true false)

Activity

Hide
Steve Miner added a comment -

This is not a bug. Check the doc – contains? refers to the keys of the collection, not the values. For a vector, the "keys" are the indices.

user=> (map #(contains? [10 20 30 40] %) (range 4))
(true true true true)

Show
Steve Miner added a comment - This is not a bug. Check the doc – contains? refers to the keys of the collection, not the values. For a vector, the "keys" are the indices. user=> (map #(contains? [10 20 30 40] %) (range 4)) (true true true true)
Hide
Ben Smith-Mannschott added a comment -

This is a (common) misusing of contains?. Perhaps it would have been better if contains? had been named contains-key?, but that ship has sailed.

Usage: (contains? coll key)

Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'.

A vector of length 4 has four keys (indexes): 0, 1, 2, 3, which is why your example is returning (true true true false).

To get the behavior your are expecting from contains?, use some:

Usage: (some pred coll)

Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)

```user> (map #(some #{%} [1 2 3 4]) [1 2 3 4])
(1 2 3 4) ; all of which are truthy
```

If you prefer booleans, you could do something like this:

```user> (map (comp boolean #(some #{%} [1 2 3 4])) [1 2 3 4])
(true true true true)
```
Show
Ben Smith-Mannschott added a comment - This is a (common) misusing of contains?. Perhaps it would have been better if contains? had been named contains-key?, but that ship has sailed.
Usage: (contains? coll key) Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'.
A vector of length 4 has four keys (indexes): 0, 1, 2, 3, which is why your example is returning (true true true false). To get the behavior your are expecting from contains?, use some:
Usage: (some pred coll) Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)
```user> (map #(some #{%} [1 2 3 4]) [1 2 3 4])
(1 2 3 4) ; all of which are truthy
```
If you prefer booleans, you could do something like this:
```user> (map (comp boolean #(some #{%} [1 2 3 4])) [1 2 3 4])
(true true true true)
```

Vote (0)
Watch (0)

• Created:
Updated:
Resolved: