After yesterdays chapter I have gone a number of chapters without really coding anything, let alone trying to code up something from scratch. Looking around for some problems to try I found to my horror that I wasn't sure how to code the first test on

Project Euler in Lisp. I kept fumbling with syntax and trying to remember what functions to use or their side effects. In the end I ended up just searching for someone's solution and learning from them. A bit of a wake up call. Even though I am learning concepts by going through and reading the book and typing in the examples and messing with them a little there is nothing to match simple exercises to learn new concepts. I might be able to read a bunch of Lisp code now, but I sure couldn't write it. So tonight I did a quick google to find some sample problems from courses and did the following one. Feel free to present your own better way to solve this problem.

Define (has-number-p s-exp) to return true if the s-expression is or contains a number.

(has-number-p '(a (b (c d) ((3)))))

T

And my solution:

(defun has-number-p (s-exp)

(if (and

(listp s-exp)

(< 0 (list-length s-exp)))

(or

(has-number-p (first s-exp))

(has-number-p (rest s-exp)))

(numberp s-exp)))

## 3 comments:

I am also a beginner in Lisp who is reading through the Practical Common Lisp book. I do not know if the following solution to yout problem is "better", but it feels somewhat "lispier". :-)

(defun has-number-p (s-exp)

(cond ((null s-exp) nil)

((atom s-exp) (numberp s-exp))

(t (or (has-number-p (car s-exp))

(has-number-p (cdr s-exp))))))

Yah my solution wasn't very elegant. Especially that call to length. I could change it to this:

CL-USER> (defun has-number-p (s-exp)

(if (null s-exp)

nil

(if (atom s-exp)

(numberp s-exp)

(or

(has-number-p (first s-exp))

(has-number-p (rest s-exp))))))

But using cond rather then nested if's is much nicer as you suggested.

I'm also a beginning lisp'er and I think I've solved this problem using the suggested "some" function, which makes it rather neat:

(defun has-number-p (x)

(cond ((atom x) (numberp x))

( 'T (some #'has-number-p x))

)

)

So what this does is first test to see if the input is an atom. If yes, return whether it's a number or not.

If the input is a list, the 'some' method will run a test on each item in the list, essentially or'ing the results. The test I want to run is the very function I'm writing, so I just call it recursively. I haven't tested this very rigorously but I think it works. The pound-singleQuote (#') construct is a way of passing a function without actually calling it right then and there.

Post a Comment