r00k
r00k

Reputation: 661

Common lisp idiom - is there a better way?

I find myself doing this sort of thing all the time. I've been considering writing a macro/function to make this sort of thing easier, but it occurs to me that I'm probably reinventing the wheel.

Is there an existing function that will let me accomplish this same sort of thing more succinctly?

(defun remove-low-words (word-list)   
  "Return a list with words of insufficient score removed."
  (let ((result nil))
    (dolist (word word-list)  
      (when (good-enough-score-p word) (push word result)))                                      
    result))  

Upvotes: 7

Views: 2141

Answers (3)

Luís Oliveira
Luís Oliveira

Reputation: 2974

There are several built-in ways of doing this. One way would be:

(remove-if-not 'good-enough-score-p word-list)

And another:

(loop for word in word-list  
      when (good-enough-score-p word)
      collect word)

And yet another:

(mapcan (lambda (word)
          (when (good-enough-score-p word)
            (list word)))
        word-list)

Etc... There's also SERIES and Iterate. The Iterate version is identical to the LOOP version, but the SERIES version is interesting:

(collect (choose-if 'good-enough-score-p (scan word-list))))

So, yes, you're very likely to reinvent some wheel. :-)

Upvotes: 22

Nathan Shively-Sanders
Nathan Shively-Sanders

Reputation: 18389

The function you want is remove-if-not, which is built-in.

(defun remove-low-words (word-list)
  (remove-if-not #'good-enough-score-p word-list))

If you feel like you are re-inventing something to do with lists, you probably are. Check the Hyperspec to see.

Upvotes: 6

Chris Hanson
Chris Hanson

Reputation: 55174

There are a couple ways you can do this. First, and probably most easily, you can do it recursively.

(defun remove-low-words (word-list)
  (if (good-enough-score-p (car word-list))
      (list word (remove-low-words (cdr word-list)))
      (remove-low-words (cdr word-list))))

You could also do it with mapcar and reduce, where the former can construct you a list with failing elements replaced by nil and the latter can be used to filter out the nil.

Either would be a good candidate for a "filter" macro or function that takes a list and returns the list filtered by some predicate.

Upvotes: -2

Related Questions