Page 1 of 1

Why don't my solutions work? Specifics inside.

Posted: Mon Jun 11, 2012 2:10 pm
by humanoid
Hi,

I'm a junior in high school learning how to program in Lisp. It's just something that I'm doing on the side, not for a course or anything. I have experience only in Java from taking the AP Computer Science class. I've just started about a week ago, and I've gotten a copy of ANSI Common Lisp and am using whatever online resources I can find. So if you guys have any suggestions for additional resources I could use or general information about what Lisp is used for nowadays or anything Lisp related, I'd be happy to listen. Anything helps. But anyways, here's my question:

I'm doing an exercise from ANSI Common Lisp that is as follows: define a function that takes a list as an argument and returns true if one of its elements is a list (using only operators introduced in chapter 2).

Here are my two solutions, neither of which work. I've seen the solution to this exercise, but I am very curious as to why my solutions don't work.

Code: Select all

(defun islist (x) 
  (if (not (listp x))
      nil
    (or (listp (car x)) (islist (cdr x)))))
also

Code: Select all

(defun islist (x)
  (and (listp x)
       (or (listp (car x)) (islist (cdr x)))))
If I said (islist '(a b c d)), the function should return nil, yet it always returns T. Also, my indentation may be wierd. I'm using Emacs right now and it only lets me tab a set amount per line. Whether that amount is correct or not I have no idea.

Thanks

Re: Why don't my solutions work? Specifics inside.

Posted: Mon Jun 11, 2012 8:15 pm
by gugamilare
You need to check whether the argument X given is NIL, in which case you should return NIL.

Re: Why don't my solutions work? Specifics inside.

Posted: Fri Jun 29, 2012 2:04 pm
by sylwester

Code: Select all

(defun islist (x)
  (and (listp x)
       (or (listp (car x)) (islist (cdr x)))))
Lets imagine we send it 'a as an argument. The first (listp 'a) => NIL and and will terminate
If its a list argument eg. '(a b c) '((a) b c) or even '() (listp x) will be T. Note that () which also represents false in CL is a list and thus (listp ()) => T.
To make matters even worse (cdr ()) => () so the function will never terminate.
Have you used it's sister function (consp x) which also returns T for all lists except the empty list ()/NIL, then it would work as you imagined. The following small change makes it work.

Code: Select all

(defun islist (x)
  (and (consp x)
       (or (listp (car x)) (islist (cdr x)))))
Since there was a restriction on which functions you could use I guess a textbook example uses (not (null x)) or just (not x) instead of (consp x) but you'll loose the case where the argument is not a list at all.

I really enjoyed the book The Land of LISP so you should look it up if you're planning to learn CL.
I also enjoyed watching the video lectures of MIT programming class Structure and Interpretation of Computer Programs where they use Scheme (different dialect).

Good luck :)