contains? on String

469 views
Skip to first unread message

Shantanu Kumar

unread,
May 12, 2015, 2:25:46 PM5/12/15
to clo...@googlegroups.com
Hi,

I notice the following in Clojure 1.7.0-beta2:

user=> (contains? "hello" 2)
true
user=> (contains? "hello" \e)

IllegalArgumentException contains? not supported on type: java.lang.String  clojure.lang.RT.contains (RT.java:800)


Is this just a case of misleading error message or am I missing something?

Shantanu

James Reeves

unread,
May 12, 2015, 2:42:19 PM5/12/15
to clo...@googlegroups.com
contains? has always been a little counter-intuitive. It essentially only works on collections that allow for a constant or logarithmic lookup time, and often works on the "keys" of a collection, rather than its values. The only exception to this are sets, where the values are essentially keys as well.

So:

    (contains? {:a 1} :a) => true
    (contains? {:a 1} 1) => false
    (contains? [:a] :a) => false
    (contains? [:a] 0) => true
    (contains? #{:a} :a) => true
    (contains? "a" \a) => error
    (contains? '(:a) :a) => error

- James

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shantanu Kumar

unread,
May 12, 2015, 2:54:07 PM5/12/15
to clo...@googlegroups.com, ja...@booleanknot.com
I agree about the counter-intuitiveness. I'm only wondering whether the error message is a bit misleading "contains? not supported on type: java.lang.String" because of course (contains? "hello" 2) works fine.

Shantanu

James Reeves

unread,
May 12, 2015, 2:57:41 PM5/12/15
to Shantanu Kumar, clo...@googlegroups.com
On 12 May 2015 at 19:54, Shantanu Kumar <kumar.s...@gmail.com> wrote:
I agree about the counter-intuitiveness. I'm only wondering whether the error message is a bit misleading "contains? not supported on type: java.lang.String" because of course (contains? "hello" 2) works fine.

Oh, I see! Yes, that is a bit misleading.

- James

Michael Gardner

unread,
May 12, 2015, 3:34:46 PM5/12/15
to clo...@googlegroups.com
On May 12, 2015, at 1:54 PM, Shantanu Kumar <kumar.s...@gmail.com> wrote:
> I agree about the counter-intuitiveness. I'm only wondering whether the error message is a bit misleading "contains? not supported on type: java.lang.String" because of course (contains? "hello" 2) works fine.

It seems odd that (contains? "abc" 2) works, at least to me. It's clearly intentional, from this line in RT.java:

else if(key instanceof Number && (coll instanceof String || coll.getClass().isArray())) {

Can anyone comment on why Strings are explicitly supported here?

Fluid Dynamics

unread,
May 12, 2015, 4:28:20 PM5/12/15
to clo...@googlegroups.com

Strings and arrays support constant-time access by index. The thing that's broken is "contains? not supported on type: java.lang.String" instead of nil when a nonnumeric key is used. One gets nil with a nonnumeric key and a PersistentVector, rather than an exception.

Lee Spector

unread,
May 12, 2015, 5:04:23 PM5/12/15
to clo...@googlegroups.com
On May 12, 2015, at 4:28 PM, Fluid Dynamics <a209...@trbvm.com> wrote:

On Tuesday, May 12, 2015 at 3:34:46 PM UTC-4, Michael Gardner wrote:
On May 12, 2015, at 1:54 PM, Shantanu Kumar <kumar.s...@gmail.com> wrote:
> I agree about the counter-intuitiveness. I'm only wondering whether the error message is a bit misleading "contains? not supported on type: java.lang.String" because of course (contains? "hello" 2) works fine.

Can anyone comment on why Strings are explicitly supported here?

Strings and arrays support constant-time access by index. The thing that's broken is "contains? not supported on type: java.lang.String" instead of nil when a nonnumeric key is used. One gets nil with a nonnumeric key and a PersistentVector, rather than an exception.

The contains? function is just badly named, spawning a couple of different kinds of confusion. 

I know it's not going to change -- the problems have been pointed out for years.

But FWIW I find it's usually best to pretend it doesn't exist, and when my students run into trouble with it I suggest that they do the same.

 -Lee

Michael Gardner

unread,
May 12, 2015, 5:05:00 PM5/12/15
to clo...@googlegroups.com
On May 12, 2015, at 3:28 PM, Fluid Dynamics <a209...@trbvm.com> wrote:
> Strings and arrays support constant-time access by index.

Yes, but why should that mean that contains? should work on Strings? "Because it can" doesn't seem compelling to me. In discussions about contains?, one often hears that it works on associative containers, which is supported by the use of the word "key" in its docstring. Vectors are indeed associative, but Strings aren't (at least according to associative?), which is why this seems like a strange feature to me.

Devin Walters

unread,
May 12, 2015, 5:39:17 PM5/12/15
to clo...@googlegroups.com
Ignoring some of the conversation here to point out that what you want is: (.contains "foo" "f")

Fluid Dynamics

unread,
May 12, 2015, 7:51:21 PM5/12/15
to clo...@googlegroups.com

Yes; and presumably you can't produce a string with one character changed using "assoc" either.

But it should work consistently. Either it shouldn't work for strings, or it should work fully, including producing nil for not-found with nonnumeric keys. Ditto arrays.

Sam Raker

unread,
May 13, 2015, 9:55:22 PM5/13/15
to clo...@googlegroups.com
I always assumed (contains? "foo" 2) worked because strings are arrays (i.e. vectors) of characters, on some level.

Erik Price

unread,
May 13, 2015, 11:15:36 PM5/13/15
to clo...@googlegroups.com
> (get "the char at index" 4)
\c

e


On Wed, May 13, 2015 at 9:55 PM, Sam Raker <sam....@gmail.com> wrote:
I always assumed (contains? "foo" 2) worked because strings are arrays (i.e.  vectors) of characters, on some level.
Reply all
Reply to author
Forward
0 new messages