0

I am working on a recursive function that takes a list and a value ex: 'b '(a. b), and returns nil if not found and t if found. my issue is in the line (cond ((eq A (car L)) t), it seems to be checking that condition even after (cond ((and (atom L (eq A L)) t) returns. I am under the impression that if that condition is met, execution stop and the function returns. Any way to fix this? Also, im only able to use primitive functions defun cond cons car cdr operators +, -, <, and > null eq listp atom symbolp

;test cases 
(checkInner 'b '(a . b))
(checkInner 'f '(c e f))
(checkInner 'b '(b))

;function 
(defun checkInner(A L)
    (cond ((and (atom L) (eq A L)) t)
    )
    (cond ((or (atom L) (eq A L)) nil)
    )
    (cond ((eq A (car L)) t)
            (t (checkInner A (cdr L))
            )
    )
)
1
  • 1
    Only the value of the last cond is returned by the function. Commented Oct 28, 2019 at 21:54

3 Answers 3

3

Unless you use an explicit (return-from checkInner value) expression, a function returns the value of its last expression. So the only value that's returned by your function is the last cond expression; the first two tests are ignored.

You need to combine all the cases into a single COND expression.

Also, the second test should not use or. If L is an atom, it won't be equal to L because we tested that in the previous case.

(defun checkInner(A L)
    (cond ((and (atom L) (eq A L)) t)
          ((atom L) nil)
          ((eq A (car L)) t)
          (t (checkInner A (cdr L)))))
Sign up to request clarification or add additional context in comments.

2 Comments

ohhh thats awesome, thanks for the advice, looks a lot better!
In a Common Lisp function, you must use (return-from <name> value); (return value) bails out of the inner-most enclosing anonymous block; but functions carry a named block.
0

so I fixed it, thanks for confirming Barmer, this is my solution

(defun checkInner(A L)
    (cond ((and (atom L) (eq A L)) t)
        (t  (cond ((or (atom L) (eq A L)) nil)
                (t (cond ((eq A (car L)) t)
                        (t (checkInner A (cdr L))
                        )
                    )
                )
            )
        )
    )
)

3 Comments

You shouldn't nest the cases, cond allows multiple cases.
"Or else" (pun not intended), if you insist on having only two-clause cond-s of the form (cond (x y) (t z)), use (if x y z) instead.
@Kaz "otherwise" (pun intended)
0

@Barmar You are basicaly checking the L being an atom twice, the first time could be written just as ((atom L) (eq A L)) (eq A L) is returning a boolean, so you don't need to explicitely return T from that clause, which overall contradicts with your second clause ((atom L) nil). Also note that this solution will not work on nested lists of elements (which would be the only argument willing to write your own recursive function and not just using the Lisp functions for testing memberships like member, find etc.)

(checkInner 'b '(a (c (d (b))))) ; => NIL

Following is a recursive definition that works on nested lists as well. Note that you can also supply an equality testing function for allowing your X being of different types.

(defun check-inner (x coll &key (test #'eq))
   "Check if X is in the collection. Works on nested lists 
and uses the test keyword argument for equality checking."
   (cond
    ((null coll) nil)
    ((listp (car coll)) (or (check-inner x (car coll) :test test)
                            (check-inner x (cdr coll) :test test)))
    ((atom (car coll)) (or (funcall test x (car coll))
                           (check-inner x (cdr coll) :test test)))
    (t (check-inner x (cdr coll :test test)))))

Now the thing you are looking for can be also hidden in nested layers in your list:

(check-inner 'b '(a (c (d (b))))) ; => T

Checking for other types is also no problem:

(check-inner "b" '(a (c (d ("b")))) :test #'string=) ; => T

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.