Reputation: 1613
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
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