2

Can anybody explain to me why this:

(remove-if #'(lambda (var) (member var (list "x"))) (list "x" "y" "z"))

returns this:

("x" "y" "z")

but this:

(remove-if #'(lambda (var) (member var (list 1))) (list 1 2 4))

returns this:

(2 4)

?

Weafs.py
  • 22,731
  • 9
  • 56
  • 78

1 Answers1

4

The Answer

Pass :test #'equal to member:

(remove-if #'(lambda (var) (member var (list "x") :test #'equal)) (list "x" "y" "z"))
==> ("y" "z")

Note that

(eql "x" "x")
==> NIL
(equal "x" "x")
==> T
(eql 1 1)
==> T

The Reason

The default One-Argument Test in Common Lisp is eql.

It is the most reasonable choice between the 4(!) general purpose comparison functions provided for by the ANSI CL standard:

  • eq is too implementation-dependent and does not work as one probably wants on numbers and characters
  • equal and equalp traverse objects and thus take a long time for huge ones and may never terminate for circular ones.

See also the difference between eq, eql, equal, and equalp in Common Lisp.

The Right Way

Use set-difference instead of remove-if + member.

Community
  • 1
  • 1
sds
  • 58,617
  • 29
  • 161
  • 278
  • Thank you so much :) still kind of a newb at this, and my mindset is still too much linked to C&C++ – Miguel Noronha Nov 10 '14 at 03:01
  • 2
    @MiguelNoronha: if your question has been answered, should should close it by [accepting an answer](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) – sds Nov 10 '14 at 03:48