See my point? Even in this incredibly simple iterative task you are forced into a clever trick leveraging how append works and then totally artificially taking each thing you want to collect and wrapping it in a list of one.
Looked at another way, you are not really going out and getting lists of variable length and then appending them, you are just using this trick to avoid collecting nils.
In this case the issue is not efficiency, it is that the loop DSL provides a more natural way for the developer to express themself. Now scale this to a loop that does three things at once, perhaps partitioning a list into several while counting or summing something else and the non-loop version explodes in complexity exponentially while the loop version gracefully grows linearally. (Say that three times fast.)
I got a little carried away with being clever in that version. But look at the canonical Arc version:
(rev:accum collect
(each y whatever
(awhen (pfft y) (collect (yo-mama (cons y it))))))
This version is pretty straightforward in expressing my intent.
As for the scaling issue, I'm still thinking about your other example. I'm not sure it's a good thing that Loop allows more and more to be tacked on. Subroutines in imperative-style languages like C++ have the same agglutinative property, and we're all familiar with the results of that.
Where on earth in your intent was reversal? Either the semantic or the run-time cost (ie, now you have introduced an efficiency issue that was not there with mappend/list.
You cannot win this fight, find a white flag, run it up. Why can you not win? Because loop the DSL was written with the most common iterative design patterns in mind, and hard-coded to make them both more succinct, more efficient, and to play well with other iterative patterns we occasionally want to run merged as one iteration.
This is what DSLs are for! Read On Lisp. We build the language up to our requirements. Loop is about iteration, and Lisp stands for list-processing. 2+2 left as an exercise. :)