Reputation: 25
Given I have the list that might vary in its' structure- it might have multiple lists within list, how do I iterate through every element? Example of the list: (or (and (not a) (not b)) (or (and x) t)))
Upvotes: 1
Views: 2041
Reputation: 48775
From SICP I remember accumulate-tree
which can be considered a reduce
for trees. In CL it might look like this:
(defun accumulate-tree (tree term combiner null-value)
(labels ((rec (tree)
(cond ((null tree) null-value)
((atom tree) (funcall term tree))
(t (funcall combiner (rec (car tree))
(rec (cdr tree)))))))
(rec tree)))
You can do stuff like adding all numbers in the tree:
(defparameter *value-tree* '(1 2 (3 4 (5 6)) 3))
(accumulate-tree *value-tree*
(lambda (x) (if (numberp x) x 0))
#'+
0) ; => 24
To implement @coredumps map-tree
you use cons
as combiner and nil
ass nil value:
(defun map-tree (function tree)
(accumulate-tree tree function #'cons nil))
Upvotes: 0
Reputation: 3452
It's a tipical situation for maptree function.
(defun maptree (fn tree)
(cond
((null tree) tree)
((atom tree) (funcall fn tree))
(t (cons
(maptree fn (first tree))
(maptree fn (rest tree))))))
So you can do (maptree #'what-to-do your-list)
.
I will just print all elements, you can provide any function you want, it'll b executed on each element of your tree.
CL-USER> (let ((lis
'(or (and (not a) (not b)) (or (and x) t))))
(maptree #'print lis))
OR
AND
NOT
A
NOT
B
OR
AND
X
T
Upvotes: 3
Reputation: 1934
This is a good case for a recursive function. You probably want something like this:
(defun iterate (l) (if (atom l) (do-something-with l) (mapcar #'iterate l)))
The function do-something-with obviously defines what you want to do with each element. Further, the mapcar could be replaced by another mapping function, depending on whether you want to accumulate the results of do-something-with or not.
Upvotes: 0