Well, I pointed out at the beginning that one can use recursion, and the implementation of the `while` construct itself uses recursion as well (in fact, you can't implement `while` without it in Elixir).
In any case, expressing the equivalent of a `while` loop with predicates and timeouts is quite syntactically noisy in Elixir - it is certainly doable, but much less clear than the imperative equivalent.
> I’m not sure I would recommend using this macro generally, but it was a fun experiment, and I love the opportunity to stretch the macro muscle a bit, especially with one like this which really shows how you extend the syntax of the language via macros
In practice, I'd probably use `Enum.reduce` or recursion for these kinds of things Elixir.
I got that. The more basic question I am interested in is why doesn't Elixir have while-loop? Is that a missing feature in all "functional languages"? And if so, why is that?
It just isn't needed, most things can be expressed using nothing more than recursion; more complex things can be expressed using `for` comprehensions, or by composing the various `Stream` APIs.
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.
Functional languages rest on two main principles: (1) Immutability (2) Transforming inputs to outputs
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.
The comment only makes sense if you are aware of the English language idiom "shooting yourself in the foot" which means to accidentally hurt yourself.
So the comment is saying that while-loops are generally a feature of object oriented languages, which have many tools (they use the term "foot-gun as a joke) that make it easy to accidentally make mistakes, so writing your own while-loop in Elixir isn't as crazy as it might seem.
Sure, the implementation of the macro is complicated, but the actual `while` construct that results is just as expressive as that of any language with a native `while`.
But that's all beside the point, this was just an exercise, and was useful in a project where the reduction in complexity it provided was handy
(in other words a language which provides it)