only marginally slower than a recursive function like traverse(). The only
remaining problem is that for an expression consisting of only one primitive
object, ex::begin() and ex::end() return the same value, so the iteration
immediately stops without visiting the one existing node. We probably need
special versions of begin()/end() for creating pre-/postorder iterators after
all.