Common Lisp.
I'm trying to determine if a string is present in a given list.
My goal is to have
(member searched-string my-list)
but I keep getting NIL
.
Why does (member "foo" '("foo" "bar"))
return NIL
?
Common Lisp.
I'm trying to determine if a string is present in a given list.
My goal is to have
(member searched-string my-list)
but I keep getting NIL
.
Why does (member "foo" '("foo" "bar"))
return NIL
?
The default value for the :test
keyword parameter is #'eql
:
If neither a
:test
nor a:test-not
argument is supplied, it is as if a:test
argument of#'eql
was supplied.
17.2.1 Rules about Test Functions - Satisfying a Two-Argument Test
Strings are not numbers nor characters, so two strings are eql
only if they are eq
(identical), but in your example you probably have two different strings allocated. You could have optimizations where string=
strings are interned by the compiler, making them eq
, but that would be an implementation detail.
Here below, the same foo
string is used to build the list, and as an argument to member
, and the call actually find the value:
(let ((foo "foo"))
(member foo (list foo "bar")))
=> ("foo" "bar")
But more generally, you want to pass a string comparison function, like string-equal
(case-insensitive) or string=
(exact case), or simply a general-purpose equality predicate; both examples below find the sarch string:
(member "foo" '("foo" "bar") :test #'equal)
(member "FOO" '("foo" "bar") :test #'equalp)
It's because (eql "foo" "foo") ; ==> nil
. While not documented in the CLHS member
uses #'eql
as the standard test. To get it to use #'equal
that also evaluates t
for structures that display the same
(equal "foo" "foo") ; ==> t
(member "foo" '("foo" "bar") :test #'equal) ; ==> ("foo" "bar")
A string is stored as an vector of characters and thus unless it is the same object eq
and eql
will evaluate to nil
while equal
checks if all the characters in the strings are eql
.
NB: (eql "foo" "foo")
can also be t
. Since it is literals and thus constant data the same code compiled will in some implementation only store "test"
once so that they become pointer equal (eq
).