Page 1 of 1

Writing my own member function

Posted: Sat Apr 20, 2013 3:46 pm
by Optimus
Hey everyone. I'm brand new to Lisp. Any help that anyone can provide would be appreciated.

I'd like to write my own 'member' function that performs exactly the same as the built-in 'member' function. Any tips on how to go about doing this, or some code that can get me started?

Re: Writing my own member function

Posted: Sun Apr 21, 2013 3:31 am
by Goheeca
Have you in mind normal functions or CLOS methods?
For overriding of an ordinary function look at conduits.

Re: Writing my own member function

Posted: Sun Apr 21, 2013 6:13 am
by Optimus
Thanks for the reply. I want normal functions.

I wrote something up last night, but it doesn't function completely properly.

Code: Select all

(defun member (iTerm iList)
	(cond ((null iList) nil)
		  ((equal iTerm (car iList)) iList)
		  (t (member iTerm (cdr iList)))
	)
)
But returning from the following calls does not yield a proper result

Code: Select all

(member 1  1)    ; should return 1, but returns that 1 is invalid argument
(member 1  '(( 0 1 2 3) 9 1 5))   ;should return (1 2 3) 9 1 5 but currently only returns 1 5

Re: Writing my own member function

Posted: Sun Apr 21, 2013 6:46 am
by Goheeca
Sorry, I misconceived your original post. Your implementation works in the same way as cl:member, but you obviously want a different behaviour. In the first example you didn't pass a list in which should be the item finded (but you want to compare atoms too?), in the second one you want recursive behaviour (not trivial, because you rather want a graphical tail of nested lists than a tail in a recursive manner).

Re: Writing my own member function

Posted: Sun Apr 21, 2013 12:57 pm
by sylwester
Optimus wrote: ...

Code: Select all

(member 1  1)    ; should return 1, but returns that 1 is invalid argument
(member 1  '(( 0 1 2 3) 9 1 5))   ;should return (1 2 3) 9 1 5 but currently only returns 1 5
The built in member function will result in an error if the second argument is not a list. (error message "*** - member: A proper list must not end with 1" in CLISP)
member does only traverse the list not lists within it. 1 is compared to (0 1 2 3), 9 and 1 and returns (1 5). That the first element happens to have a 1 in it's structure is irrelevant.

You should correct your tests as the implementation is correct :)

Re: Writing my own member function

Posted: Sun Apr 21, 2013 3:42 pm
by Optimus
I see. So I guess I want a modified function that will return my desired result for:

Code: Select all

(member 1  '(( 0 1 2 3) 9 1 5))   ;should return (1 2 3) 9 1 5 but currently only returns 1 5
My current code, which was revised to compare atoms as well, is provided below.

Code: Select all

(defun member (iTerm iValues) ; S is search term, L is list
	(cond ((null iValues) nil)
		  ((equal iTerm iValues) iValues)
		  ((equal iTerm (car iValues)) iValues)
		  ((member iTerm (cdr iValues)))
	)
)
Goheeca, your last comment about graphical tail of nested lists went over my head.

Re: Writing my own member function

Posted: Mon Apr 22, 2013 1:19 am
by Goheeca
OK, this function provides the desired functionality, but I don't know what is it good for? Why do you need such a function? Is it some kind of exercise?

Code: Select all

(defun my-member (term list)
  (cond ((atom list) (when (equalp term list) term))
        ((null list) nil)
        ((and (listp (car list))
              (my-member term (car list)))
         (cons (my-member term (car list))
               (cdr list)))
        ((equalp term (car list)) list)
        (t (my-member term (cdr list)))))