I think `while` can more succinctly express certain patterns, but that window is pretty narrow, so adding an additional keyword to the language that has so much overlap with other options just doesn't make sense.
Elixir is a little unique in that it has no mutability, so fundamentally a `while` loop isn't really a thing that makes sense - you can't mutate anything in the containing scope, so you are left with basically nothing useful you can do. The macro I build in this post is a clever way of making it work, but only with the bindings given to the macro, and it isn't actually mutating them.
For other FP languages that are immutable, they likely don't have a `while`, or provide some kind of machinery that emulates it (like Haskell's monadic loops). For FP languages with opt-in mutability, they might have `while`, just depends on the language.
Shared mutable states creates a lot of accidental complexity and makes writing concurrent applications harder. I recommend the talk "The Value of Values" by Rich Hickey for a more in depth analysis.
A traditional while loop like while (x < 5) { ... } involves mutating state, so it's not possible to implement in a purely functional language. In the case of bitwalker's implementation, a value is returned to work around this limitation.