0

I have some lisp code that I have to write multiple different ways. I've tried two different ways and I'm unsure of why they don't work. The function has to take a list and return only integers in that list. The first one has to take a map function and the second one has to use loop. This is in Clisp.

Here is my code.

(defun posint1 (l)
  (mapcan #'(lambda (x)
              (and (integerp x)
                   (list l)))))

and

(defun posint1 (l)
  (loop for x in (list l)
        when (integerp x)
        collect x)
  (format t "~A " x))))
2
  • 1. Why do you call list on l which already is a list? 2.Check the number of arguments to mapcan. Commented Sep 10, 2015 at 14:09
  • Thanks. I managed to fix the first one do to your suggestion. Commented Sep 10, 2015 at 14:41

1 Answer 1

2

mapcan requires at least one list argument and you have supplied none in your first function (I can't use names since you call both the same)

The second function tried to format a variable, x, that does not exist in that scope. In loop x are the one element in (list l) which probably should just be l since making a one number list doesn't really need iteration. Perhaps you wanted something like:

(defun print-integers (list)
  (loop :for x :in list
        :when (integerp x)
        :collect x :into result
        :finally (format t "~A " result)))

;; or using the result as argument
(defun print-integers (list)
  (format t
          "~A "
          (loop :for x :in list
                :when (integerp x)
                :collect x)))

(print-integers '(-1 0.5 1/3 +inf.0 9)) ; ==> NIL (prints (-1 9)

Also notice that integerp works for whole numbers, also negative ones. The name hinted that you might want to use (and (integerp x) (>= x 0)) instead.

Sign up to request clarification or add additional context in comments.

3 Comments

This worked for me and I understand the logic behind it. My only question, which might be dumb, is about syntax. Why doesn't when, collect, and finally get parenthesis?
@user2161813 LOOP is a macro. Under the hood, there's a macroexpansion function that's called with all the stuff within the LOOP form, and it translates it into code that can actually be run. Since that transformation occurs, the stuff inside LOOP doesn't have to have the same syntax as typical code. Try (macroexpand-1 '(loop for x from 1 to 10 collect x)) to see what kind of transformations happen.
@user2161813 It's just a design choice. The different lisp versions made loop macros and interlisp was first with for, but the most copied features was MacLisps loop which was adopted by the Lisp Machine lisps. Since it was most common it made the standard. There is an iterate macro that is just like loop but with more lispy look. Which is best is a matter of taste :-)

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.