Yep, it could be a good way in some instances. But for this particular I don't think it needs to be done like that. Nothing wrong with it, I just can't see (in this case) that it brings anything better than a much simpler method.
Good one with the iterative! You're correct since for this (and other nested structures like trees & networks) it's usually simpler and quicker to use recursion. The problem with iteration in these cases is that you always need one or more temporary lists which grows and shrinks constantly as you run through different levels, this itself takes time. Then as you've found, sometimes you need to iterate over the entire structure twice if you don't want to recurse. You'll see nearly all samples of coding pertaining to trees are using some sort of recursion, there are very few iterative samples (even through google) because it's so much more complex and usually slower AND usually uses a lot more RAM.
That's not to say iterative is always like this, it's just the "nested" which causes this issue. In general recursion tends to be slower than iterative if you only run through a normal list, and could even use more ram as well. E.g. testing my own rolled foreach loop doing it through recursion and another through while:
(defun foreach
-recursive
(var lst code
) (foreach
-recursive var
(cdr lst
) code
))))
(defun foreach
-iterative
(var lst code
)
The benchmark
$ (setq test '(1 2 3 4 5 6 7 8 9))
(1 2 3 4 5 6 7 8 9)
_$ (quickbench '((foreach-recursive 'x test '(1+ x)) (foreach-iterative 'x test '(1+ x)) (foreach x test (1+ x))))
Benchmarking ... done for 16384 iterations. Sorted from fastest.
Statement Increment Time(ms) Normalize Relative
--------------------------------------------------------------------------------
(FOREACH X TEST (1+ X)) 16384 1187 1187 5.20
(FOREACH-ITERATIVE (QUOTE X) TEST (Q...) 4096 1264 5056 1.22
(FOREACH-RECURSIVE (QUOTE X) TEST (Q...) 4096 1543 6172 1.00
--------------------------------------------------------------------------------
Of course using the built-in foreach is a lot quicker as it's fully compiled (probably written in C as well).
Anyhoo! You're welcome to the QuickBench. It's not perfect though, there are some others which are slightly more accurate. I just use it as the 1st benchmark to weed out the really slow code before I use one of the other benchmark routines to figure out exactly which code is fractionally faster than the other. Though more often than not I don't bother too much if there's only a 1% (or so) difference.