Edit -- After a useful discussion with Timothy Pratley about clojure.walk
After looking at the source code of clojure.walk I have come up with a third square-tree function that extends the square-tree2, but now preserves the input collection types of the input tree like clojure.walk does:
(defn square-tree3
[tree]
(cond
(list? tree) (apply list (map square-tree3 tree))
(seq? tree) (doall (map square-tree3 tree))
(coll? tree) (into (empty tree) (map square-tree3 tree))
:else (square tree)))
So it extends the answer to the coll? predicate with a (into (empty tree)...) which puts the result of map into whatever type of collection tree is. It also adds cases for list and seq types, handling each of them in their own special way so that they replicate into the same collection type.