5 ms·
No loops? That can be life changing.
by wolco 8y ago
No loops? That can be life changing.
- Jtsummers 8y agoI don't know Elixir, but I do know Erlang (one of Elixir's inspirations). The lack of loops is replaced by recursion or higher level functions. Tail calls (all, not just recursive) are optimized so that you don't blow the stack. Since the two (iteration and recursion) are easily transformed into the other, it's a pretty clean mode of coding.
- tim333 8y agoYou can sort of loop in Elixir eg. Enum.map(1..100, &IO.puts/1) prints the numbers 1 to 100
- xtian 8y agoWell, there is also a `for` construct: for i <- 1..100, do: IO.puts(i) I guess what people mean is that that’s an abstraction over function calls?
- derefr 8y agoIf you’re wondering: Erlang (and so Elixir) has a very “pragmatic” design behind its abstract machine/runtime; it’s not like the lack of loops is to be functionally pure or anything. They remove loops in the Erlang abstract machine so that there are only ever O(1) instructions executed between each function call (where a tail-recursion is considered a function call.) With this constraint in place, the runtime can get away with a hybrid of cooperative and preemptive scheduling called “reduction scheduling”, where functions only ever yield when they make a function call (or return from one.) By ensuring every function body has O(1) “reductions” before it hits a CALL or RET op, the runtime guarantees (unlike cooperative scheduling) that execution will always yield from a task in a bounded amount of time; and by ensuring yields only happen at call-sites, the runtime ensures that (unlike preemptive scheduling) there is no register state to preserve at time of yield—all the scheduler has to record when it pauses a task is the thunk (function pointer + parameter list) for the call it was about to make. Together, these guarantees allow for extremely low-overhead context switching between tasks in a soft-realtime context. Other systems (e.g. .NET’s Orleans) simulate this hybrid approach by splitting code into state machines with explicit yield points being the state transitions. But AFAIK, only ERTS takes the approach of making function calls into the state transitions. (Because, without the no-native-loops constraint, such an approach doesn’t work at all.)
- rad_gruchalski 8y agoRecursion is the way to go in Erlang / Elixir: https://learnyousomeerlang.com/recursion https://learnyousomeerlang.com/recursion When one writes a bit if Erlang for a while, one gets a completely different view on any software to be written in the future. Erlang is life changing. But there are things where other technologies are better fit.
- kbp 8y ago> Recursion is the way to go in Erlang / Elixir I think it's important to realise that they're different ways of writing the same thing. For example, in Lisp, the 'do' operator is basically a C-style for loop: in Scheme, it's a macro over tail recursion, and in Common Lisp, it's a macro over gotos, but it provides an almost identical interface to programmers. Using recursion over loops is just a stylistic/syntactic choice, the really important part is understanding how recursive functions are equivalent to loops, and vice versa, so that you can apply your experience in one situation to the other.
- rad_gruchalski 8y agoHence I said “in Erlang / Elixir”. Because, really, in those two, recursion IS the only way to go.
- kbp 8y ago> No loops? That can be life changing. I doubt it would be for someone from a Ruby background, where higher order functions already generally replace built-in loops.