This is a collection of blog entries written while learning Lisp. It is posted in the order written so you probably want to jump to the first post.

Thursday, October 25, 2007

ANSI Common Lisp Chapter 2 : Welcome to Lisp

A nice good intro to Lisp diving straight into the prompt touching on prefix notation, lists, and expressions. Unlike Practical Common Lisp car cdr are introduced in the first chapter vs using first and rest. The first chapter also introduces a number of simpler built in macros, such as if, not, and listp. Then some functions, a quick recursion lesson, tips on reading and writing lisp code (indenting), basic io, and variables, functional programming, iteration. None of the sections go into any depth and macros are no where to be seen. This has to be one of my favorite technical book techniques in the first chapter to present how to do what people already know in the new language/tool.

And now for the fun part!


1. Describe what happens when the following expressions are
evaluated:

a. (+ (- 5 1) (+ 3 7))

14

b. (list 1 (+ 2 3))

(1 5)

c. (if (listp 1) (+ 1 2) (+ 3 4))

7

d. (list (and (listp 3) t) (+ 1 2))

(nil 3)

2. Give three distinct cons expressions that return (a b c).

(cons 'a '(b c))
(cons 'a (cons 'b '(c)))
(cons 'a (cons 'b (cons 'c nil))

3. Using car and cdr, define a function to return the fourth
element of a list.

(defun foo(lst)
(car (cdr (cdr (cdr lst)))))

4. Define a function that takes two arguments and returns the
greater of the two.

(defun foo(a b)
(if (> a b)
a
b))

5. What do these functions do?

a. (defun enigma (x)
(and (not (null x))
(or (null (car x))
(enigma (cdr x)))))

(updated)
Returns true if any item in the list is a null list.

b. (defun mystery (x y)
(if (null y)
nil
(if (eql (car y) x)
0
(let ((z (mystery x (cdr y))))
(and z (+ z 1))))))

Returns the location of x in y or nil if it does not.

6. What could occur in place of the x in each of the following
exchanges?

a. > (car (x (cdr '(a (b c) d))))
B

car

b. > (x 13 (/ 1 0))
13

or (good one!)

c. > (x #'list 1 nil)
(1)

apply

7. Using only operators introduced in this chapter, define a
function that takes a list as an argument and returns true if
one of its elements is a list.

(defun foo (lst)
(if (null lst)
nil
(if (listp (car lst))
t
(foo (cdr lst)))))

8. Give iterative and recursive definitions of a function that

a. takes a positive integer and prints that many dots.

(defun foo(x)
(do ((i x (- i 1)))
((< i 1))
(format t ".")))

(defun foo(x)
(format t ".")
(if (not (> 2 x))
(foo (- x 1))))

b. takes a list and returns the number of times the symbol a
occurs in it.

(defun foo(lst symbol)
(if (null lst)
0
(if (eql symbol (car lst))
(+ 1 (foo (cdr lst) symbol))
(+ 0 (foo (cdr lst) symbol)))))

(defun foo (lst symbol)
(do ((z 0) (l lst (cdr l)))
((null l) z)
(if (eql symbol (car l))
(setf z (+ 1 z)))
z))

9. A friend is trying to write a function that returns the sum of
all the non-nil elements in a list. He has written two versions
of this function, and neither of them work. Explain what's
wrong with each, and give a correct version:

a. (defun summit (lst)
(remove nil lst)
(apply #'+ lst))

Remove returns the list with nil's, you need to setf it.

(defun summit (lst)
(setf lst (remove nil lst))
(apply #'+ lst))

b. (defun summit (lst)
(let ((x (car lst)))
(if (null x)
(summit (cdr lst))
(+ x (summit (cdr lst))))))

It never ends because it never checks if lst is null.

(defun summit (lst)
(if (null lst)
0
(let ((x (car lst)))
(if (null x)
(summit (cdr lst))
(+ x (summit (cdr lst)))))))

2 comments:

Максим said...

About question 5:
as for me the correct code should be
(defun enigma (x)
(if (null x) t
(and
(defun enigma1 (x)
(and (not (null x))
(or (null (car x))
(enigma1 (cdr x)))))
(funcall #'enigma1 x))))

otherwise, it will return nil for (enigma ()) which is not correct.

what do you think? i'm more than a newbie as i have just started programming two days ago. so i'd like to hear some seasoned advice

Bogdan Creanga said...

Why the first summit couldn't be just:

(defun summit (lst)
(apply #'+ (remove nil lst)))