Among the different ways to tackle iterative processes I consider to be the higher-order function route the one I use most often. Especially in conjunction with function composition and list predicates it makes great filtering-style code.
A problem that came up several times is interrupting the list processing at an arbitrary point. For example, how do I stop MAPCAR at the third item if I see it fit? Something like that:
(let ((i 0))
(mapcar (lambda (x)
(when (eql (incf i) 3)
(STOP-HERE)))
'(a b c d)))
Sometimes, one can take alternative routes using FIND or other functions. And there’s always LOOP, DOLIST, recursion and other solutions; after all we’re working in a language that really implements the “there’s more than one way to do it” paradigm.
Using TAGBODY and GO:
(tagbody (mapcar (lambda (x) (go X)) '(a b c)) X)
Using BLOCK/RETURN-FROM:
(block X (mapcar (lambda (x) (return-from X)) ‘(a b c)))
I originally posted another version using CATCH/THROW, but as pointed out in the comments this wasn’t all well for several reasons.
Delimited continuations with CL-CONT unfortunately won’t work.
A good alternative solution would be writing your own version of MAPCAR; this has the advantage of being able to return the partially processed list. But there’s the disadvantage of having to rewrite the whole family of mapping functions, though, so for quick prototyping or occasional usage I prefer the above solution.
If you have other neat solutions or see problems with this approach, please leave a comment.