Another edit: I am not a Functional programmer, and have never known Haskell or any Lisp. Erlang is as close as I've ever gotten. I've found Rust to be a fantastic language for writing Functionally.
This is a perfectly reasonable solution. You might be leaving performance on the table but
1) if perfomance isn't a measurable problem for you, then there's on point on eking the last bit of performance from these allocations
2) it simplifies the code itself
3) sometimes clones are actually efficient, people forget to make their small ADTs Copy
4) if you're learning the language this lets you delay the moment when you have to fully understand the way lifetimes actually behave in complex cases, which means that when you do do that you will have a better grasp of the rest of the language and will be able to form a better mental model of how it fits with other features
* If you need to keep unchanged the input, you must either use a reference-to (.iter()) or copy-of (.iter().cloned()) of each item
* If you don't need the input ever again, you should move the items (.into_iter())
These rules follow for each step of the chain.
I very very often write very Functional code in Rust and I find it natural and easier to reason about than imperative-style code. The example I could find the fastest: https://github.com/thenewwazoo/aoc2019/blob/master/src/day10...
Edit: another example (this one uses types that are Copy so the copies are implicit) https://github.com/thenewwazoo/cryptopals/blob/master/src/tr...
Another edit: I am not a Functional programmer, and have never known Haskell or any Lisp. Erlang is as close as I've ever gotten. I've found Rust to be a fantastic language for writing Functionally.