The member function works like this with strings:
CL-USER> (member "a" '("a" "b" "c") :test #'equalp)
("a" "b" "c")
CL-USER> (member "a" '( "b" "c") :test #'equalp)
NIL
I would like to slightly change its behavior. When the element is not part of the list, I would like to have as a return the element itself and not nil
. Moreover, if the element is indeed part of the list, I would like to have nil
.
So, something like:
CL-USER> (tweaked-member "a" '("a" "b" "c") :test #'equalp)
NIL
CL-USER> (tweaked-member "a" '( "b" "c") :test #'equalp)
"a"
Thus, I did this naive approach:
(defun so-question (str str-list)
(if (member str str-list :test #'string=)
nil
str))
Is there a more elegant way of doing this?
Maybe using member-if-not
and :key
?
I don't know if this is more elegant; your "naive" solution might be more clear, but you could do this:
(defun tweaked-member (needle haystack)
(and (not (member needle haystack :test #'equalp)) needle))
CL-USER> (tweaked-member "a" '("a" "b" "c"))
NIL
CL-USER> (tweaked-member "a" '("b" "c"))
"a"
You could use find
in place of member
:
(defun tweaked-member (needle haystack)
(and (not (find needle haystack :test #'equalp)) needle))
I didn't notice until now that my version does not take a :test
argument, as you asked. But:
(defun tweaked-member (needle haystack &rest args)
(and (not (apply #'member needle haystack args)) needle))
CL-USER> (tweaked-member "a" '("a" "b" "c") :test #'equalp)
NIL
CL-USER> (tweaked-member "a" '("b" "c") :test #'equalp)
"a"