2

I'm new on lisp and I'm trying to solve some basic exercises. I'm trying to make a list of elements in an input list that are out of max and min limits. I've been trying to do this by creating two functions. The first one is setting the limits, the second one is running this first function for every element in a list, but my code only prints the input list.

(defun limits (x)
  (setq out nil)
  (if (> x 2)
      (push (list x) out)
      (if (< x 5)
          (push (list x) out)
          ())))

(defun out-of-limits (l)
  mapcar #'limits l)
7
  • 1
    You're missing the () around the call to mapcar. So you never call it. Commented Nov 19, 2024 at 17:01
  • There's no reason to make out a global variable. Make it a local variable with let. Commented Nov 19, 2024 at 17:03
  • Also, you need to return out at the end. Commented Nov 19, 2024 at 17:04
  • The condition (< x 5) will always be true. Any number that's not more than 2 is guaranteed to be less than 5. I suspect the second condition should be (> x 5) Commented Nov 19, 2024 at 17:07
  • Why are you pushing (list x) instead of just x? Commented Nov 19, 2024 at 17:07

1 Answer 1

3

As was explained in the comments, for a function call to be made it must be enclosed in parentheses:

> (defun out-of-limits (l)
     (mapcar #'limits  l) )
  ;  ^                  ^       here

Now calling (out-of-limits (list 1 2 3)) is the same as calling

(list (limits 1) (limits 2) (limits 3))

This means we don't need to try to push the results into any variable like out by hand. They will be collected into a return list anyway.

Thus we just need to write

(defun limits (x)
  (if (> x 2)
      (list x)
      (if (< x 5)
          (list x)
          ())))

but this is the same as

(defun limits (x)
  (if (or (> x 2) (< x 5))
      (list x)
      ()))

Let's now try it

> (out-of-limits (list 1 4 10))
((1) (4) (10))

Indeed the or test is wrong. Do you now see why?

That's right. Any number will satisfy it. Any number is either greater than 2 or smaller than 5. The two regions are overlapping.

But you meant to keep numbers that are either smaller than the lesser limit, or greater than the larger limit. We need to change the test accordingly, to

(defun limits (x)
  (if (or (< x 2) (> x 5))
      (list x)
      ()))

Now we have

> (out-of-limits (list 1 4 10))
((1) () (10))

What's left is to append all these inner lists together into one. This is achieved by using #'mapcan instead of #'mapcar:

(defun out-of-limits (l)
     (mapcan #'limits  l))

Now all the internal parentheses will disappear. Testing, we get

> (out-of-limits (list 1 4 10))
(1 10)

as required.

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

Comments

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.