with this data:
(def html
'(html (head (title "the fortune cookie institute"))
(body
(h1 "Welcome to the Fortune Cookie Institute")
(p "Our fortunes are guaranteed accurate no matter what.")
(br)
(div (p "Like these"))
(ol
(li "You will gain weight")
(li "Taxes will rise")
(li "Fusion power will always be 50 years away"))
(br)
(p "Submit your own fortunes to fortunes@fci.org!"))))
Option 1: using builtin clojure walk:
(require '[clojure.walk :refer [prewalk]])
(prewalk (fn [x] (if (= x 'p) 'h2 x)) html)
Note that the walker continues to walk and would find a 'p in places other than the head of a list (not desired).
Option 2: using specter:
(require '[com.rpl.specter :refer [ALL FIRST setval recursive-path]] )
(setval [ALL (recursive-path [] RECURSE
(cond-path
[sequential? FIRST (pred= 'p)] FIRST
sequential? [ALL RECURSE]))]
'h2
html)
specter here is only looking for 'p at the head of a list (using sequential? rather than list? as your structure is quite close to hiccup which would use vectors. sequential worls for lists and vectors.
option3:
(defn shout [html]
(if-not (sequential? html)
html
(if (= 'p (first html))
(cons 'h2 (->> (rest html)
(map shout)))
(map shout html))))
This i think truely recurses and consumes stack but the depth of html is not such that it would ever matter. I'm not sure if there is a loop [h html] ... (recur ...
answer that is better.