0

I am trying to make a function that counts the number of lists within a list.

 (defun test (a)
           (if (equal a nil) (return-from test 0))
           (if (not (listp a)) (print "case a") (return-from test (+ 0 (test (cdr a))))
             (print "case b")(return-from test (+ 1 (test (cdr a)))))
           )

I don't know how the debugger works so I tried some newbie debugging with print statements. The code above does not even execute. I have no idea why. The original code, which works but gives the wrong answer is as follows:

 (defun test (a)
           (if (equal a nil) (return-from test 0))
           (if (not (listp a)) (return-from test (+ 0 (test (cdr a))))
             (return-from test (+ 1 (test (cdr a)))))
           )

This is returning the number of elements period, whether lists or not. I don't see where I am going wrong. Another problem too, it crashes when I call (test 1) or test on any atom. Of course, you cannot take cdr of an atom but what error checking can I do? What changes can I make to make this ridiculous function work?

4
  • 2
    OK, I regret having shown you the return-from example ;-) Again, cond would saved you here. Commented Feb 18, 2014 at 16:33
  • I was not sure about the cond... Meaning in the way it works. Does it check every statement after it finds the first one true or does it only execute the first true statement? That is the only reason I didn't use it. Thanks again for the patience and help! Commented Feb 18, 2014 at 16:48
  • @user3270407 If you use Common Lisp, there is info about cond here: clhs.lisp.se/Body/m_cond.htm In most lisps cond behave the same. Commented Feb 18, 2014 at 17:58
  • Only the first one that's true. See clhs.lisp.se/Body/m_cond.htm. Commented Feb 18, 2014 at 18:00

1 Answer 1

4

The first block doesn't work because function "if" deals at most with 3 forms in it (condition then-branch else-branch). If you want a few actions in one branch, you should wrap them with progn:

(if (not (listp a))
  (progn
    (print "case a")
    (return-from test (+ 0 (test (cdr a)))))
  (progn
    (print "case b")
    (return-from test (+ 1 (test (cdr a))))))

Problem with second one is check (listp a). You should check whether first element is list rather than whole list is list (listp (car a)).

I don't know, what dialect of lisp you are using. In most of them form "cond" is available, and special form "return-from" doesn't required. So, you can rewrite you function as follows:

(defun test (a)
  (cond
    ((not (listp a)) nil) ; "atom" case
    ((not a) 0) ; empty list case
    ((listp (car a)) ; first element is list
     (print "case list")
     (+ 1 (test (cdr a))))
    (T ; fist element is not list
     (print "case not list")
     (test (cdr a))))) ; avoid adding zero because it has no effect
Sign up to request clarification or add additional context in comments.

9 Comments

Why not return 0 if a is not a list? The function is supposed to yield a number.
Yes, progn executes all forms and returns result of last one.
Thank you all. I am sorry to keep asking the Lisp questions!
@YuriyKovalev Not sure I get you. (test 1) should return 0, not nil.
@user3270407: If you are using Common Lisp, all of the chapters of Practical Common Lisp are available online: gigamonkeys.com/book. Also look at the Common Lisp Hyperspec for specific function by function documentation.
|

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.