Search code examples
lispcommon-lisp

How remove a sublist out of list?


I want to remove a special list out of my list. But the function remove donthelp me with this problem.

Its for a deepsearch in a list and I want to throw it out. I tried it with function remove but it does not work.

(DEFPARAMETER WB '((HALLWAY EAST OFFICE) (OFFICE WEST HALLWAY) (OFFICE NORTH KITCHEN) (KITCHEN SOUTH OFFICE) (BEDROOM WEST GARDEN) (GARDEN EAST BEDROOM) (GARDEN WEST OFFICE) (OFFICE EAST GARDEN) (GARDEN NORTH BATHROOM) (BATHROOM SOUTH GARDEN) (LAVATORY SOUTH BEDROOM) (BEDROOM NORTH LAVATORY) (LAVATORY WEST BATHROOM) (BATHROOM EAST LAVATORY) (BATHROOM WEST KITCHEN) (KITCHEN EAST BATHROOM) (STUDIO EAST KITCHEN) (KITCHEN WEST STUDIO) (STUDIO SOUTH HALLWAY) (HALLWAY NORTH STUDIO)))

(REMOVE '(BATHROOM EAST KITCHEN) WB) ;should throw (BATHROOM EAST KITCHEN) out of WB but does not work 
(REMOVE '(1 2 3) '((4 5 6) (1 2 3)))
My expected result is ((4 5 6))
But the output is ((4 5 6) (1 2 3))

Solution

  • The default value for the :test keyword argument in REMOVE (and more generally functions that accept a test function parameter) is EQL.

    When you write (remove '(1 2 3) '((1 2 3) (4 5 6))), you have no guarantee that both lists that print as (1 2 3) are identical. They are likely to be represented by different cons cells:

    (eql '(1 2 3) '(1 2 3))
    => NIL
    

    A compiler could detect both lists are equal at compile-time and use the same underlying memory, making them EQ, but you generally cannot assume this is the case.

    If however, you used twice the same list, REMOVE would work as you expect:

    (let ((a '(1 2 3))) (remove a (list a '(4 5 6))))
    => ((4 5 6))
    

    The above example could be also written as follows with reader variables (the result is similar, but the whole list is quoted instead being created at runtime with list):

    (remove '#1=(1 2 3) '(#1# (4 5 6)))
    => ((4 5 6))
    

    In the general case, when you don't manipulate objects by their identities, you need to use a test function that knows how to compare lists, so that different lists with the same content are considered equal:

    (remove '(1 2 3) '((1 2 3) (4 5 6)) :test #'equal)
    => ((4 5 6))
    

    With the above code, elements are compared with EQUAL.