ocxt
ocxt

Reputation: 19

Making a recursive call from the loop macro

I'm pretty new to common lisp and I've been stuck on a particular problem. The function I'm suppose to write takes in two parameters: a function and a List. It iterates through the list and calls the given function on each element in the list. If the function returns true then the element is added to a sub list that is returned

What I've tried so far is:

(defun myFunc(f l)
  (loop for x in l
        if (listp x) do (myFunc f x)
        else if (eql t (funcall f x))
        collect x
        )
  )

The function I've been given for f takes a parameter and if it's is an number, returns true. So far my code works if aList is a simple list such as (1 2 3). However when I input a nested list like (1 2 (4 5) 7) only (1 2 7) is outputted rather than (1 2 (4 5) 7).

I'm assuming it has something to do with my recursive call and what is returning. Would really appreciate some help on this

Upvotes: 1

Views: 109

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70257

There are a couple of minor issues. First off, I assume it's just a typo, but you need to replace aFunc with f (as there's no variable aFunc in your code).

Now to the main point of the question. In your else if branch, you correctly collect the value when the predicate is true. But in your recursive case, you simply run some code and discard the result. You're going to want to collect there too.

(defun myFunc (f l)
  (loop for x in l
        if (listp x)
          collect (myFunc f x)
        else if (eql t (funcall f x))
          collect x))

Finally, just a style note. It's generally more idiomatic to treat a predicate as true if it returns anything truthy, not just t. So if I was writing this, I'd probably replace (eql t (funcall f x)) with simply (funcall f x). If this is a homework assignment and the teacher told you to do it the other way, stick with that. But if it's for your benefit, you may consider changing that as well.

Upvotes: 3

Related Questions