Jason
Jason

Reputation: 1613

Member function not work in cons structure

I write two program one is to takeoutAllButLast , other is takeoutSecondLast.

I initially use the member function to determine whether there is more X behind.

And I try some data and find that:

If the first argument is a symbol, they both work!

But if it is cons structure, they both fail.

1.// `(a b)   `((b b)(a b)(b c)(a b)) ==>  `((b b)(b c)(a b)) 

(defun takeoutAllButLast (X L)
(cond ((null L) nil)
       ((equal X (first L)) 
           (if (member X (rest L)) 
               (takeoutAllButLast X (rest L)) 
               L)) 
       (t (cons (first L) (takeoutAllButLast X (rest L))))
)
)

2.//`(a b)   `((a b)(b b)(a b)(b c)(a b)) ==>  `((a b)(b b)(b c)(a b)) 
(defun takeoutSecondLast (X L)
(cond ((null L) nil)
       ((equal X (first L)) 
           (if (member X (rest (member X (rest L))))
    (cons (first L) (takeoutSecondLast X (rest L)))
    (rest L)
           )
    )
   (t (cons (first L) (takeoutSecondLast X (rest L))))
 )

What I want to ask is how to determine whether there is still one element is X behind, and can be used like member function?

And why member function cannot be used to compare cons structure?

Thx for you reading my question!

Upvotes: 0

Views: 300

Answers (1)

Vatine
Vatine

Reputation: 21248

member defaults to using eql as its equality predicate. That works fine on symbols, numbers and a few other things (that is (eq 'a 'a) is always true, (let ((cons (cons 'a 'a))) (eql cons cons)) is always true, but (eql (cons 'a 'a) (cons 'a 'a)) is almost never true).

You can pass an alternative equality checker to member using the :test keyword and if you use #'equal you will (probably) get what you want.

If you want to call member with the custom equality checker foo, simply do:

(member thing-to-check-for the-list-to-check :test #'foo)

Upvotes: 2

Related Questions