Vlad Potra
Vlad Potra

Reputation: 309

OR, AND a result from mapcar - lisp

My task is to find if a given element is contained in a list (non-linear list). This is what I've written for now, but the return value from this function is a list, which I don't really understand why.

(setq E 4)

(defun IsMember (L)
  (cond
    ((equal E L)
      T
    )

    ((atom L)
      NIL
    )

    (T
      (or (mapcar 'IsMember L))
    )
  )
)

(print (IsMember '(1 2 3 (((4) 5) 6))))

The returns value is: (NIL NIL NIL (((T) NIL) NIL)) But it should really output T or NIL if E is not found in the given list.

Upvotes: 0

Views: 369

Answers (3)

Rainer Joswig
Rainer Joswig

Reputation: 139381

Your code:

(defun is-member (l e)
  (cond

   ((equal e l)
    t)

   ((atom l)
    nil)

   (t
    (some #'(lambda (a)
              (if (equal t a) t nil))
          (mapcar #'(lambda (b) (is-member b e)) l)))))

Get rid of IF

You test if something is T and then you return T. You can get rid of that.

(defun is-member (l e)
  (cond

   ((equal e l)
    t)

   ((atom l)
    nil)

   (t
    (some #'(lambda (a)
              (equal t a))
          (mapcar #'(lambda (b) (is-member b e)) l)))))

Get rid of EQUAL

Since the list consists of T and NIL, EQUAL can be replaced, too

(defun is-member (l e)
  (cond

   ((equal e l)
    t)

   ((atom l)
    nil)

   (t
    (some #'identity
          (mapcar #'(lambda (b) (is-member b e)) l)))))

Get rid of MAPCAR

Since MAPCAR returns a list of T and NIL, we can remove that, too.

The result:

(defun is-member (list e)
  (cond ((equal list e)  t)
        ((atom list)     nil)
        (t               (some (lambda (b) (is-member b e))
                               list))))

Get rid of COND condition/value pairs

Since COND is used like an OR, we can replace COND with OR. We don't need to have the condition/value pair anymore:

(defun is-member (list e)
  (or (equal list e)
      (and (consp list)
           (some (lambda (b) (is-member b e))
                 list))))

Upvotes: 6

coredump
coredump

Reputation: 38924

Your solution can be rewritten more simply as:

(defun is-member (element tree)
  (flet ((recurse (e) (is-member e tree)))
    (or (equal element tree)
        (and (consp tree)
             (some #'recurse tree)))))

But you do not even need to use some:

(defun is-member (element tree)
  (or (equal element tree)
      (and (consp tree)
           (or (is-member element (car tree))
               (is-member element (cdr tree))))))

Upvotes: 2

Vlad Potra
Vlad Potra

Reputation: 309

Thanks for help, managed to not use OR anymore

(defun IsMember (L E)
  (cond
    ((equal E L)
      T
    )

    ((atom L)
      NIL
    )

    (T
      (some #'(lambda (A) (if (equal T A) T NIL)
            (mapcar #'(lambda (B) (IsMember B E)) L))
    )
  )
)

Not sure if ethical enought but does the job...

Upvotes: 0

Related Questions