Yall really just write procedural code for everything?
Yall really just write procedural code for everything?
I use Python plenty, just not in large enough doses that I have to actually make peace with it.
Another non-functional application of tail call elimination is finite state machines. Writing them as functions calling the next state in tail call position is very elegant, legible and efficient.
Were it not for Firefox and Edge teams who torpedoed that feature, it would be a part of the major language of today.
Maybe it still will be.
Julia code might also uses a lot of in place operations which would be hard for a compiler to infer as safe.
No, I AM going to write procedural code, and it WILL be faster than your "high IQ" 1 line recursive solution. Also funny to see how little recursion gets used in CUDA/Pytorch/GPU programming - which is what we are seeing to be more and more important over time.
Well, for example at the very least in Common Lisp you'll have much more joy with higher-order functions than with loops. The simple reason for that is the existence of compiler macros (http://clhs.lisp.se/Body/03_bba.htm) which can replace function compositions with arbitrary code. And it's much easier to figure out what the function composition does than to write a loop vectorizer.
Julia also has similar macro capabilities to common lisp.
> And it's much easier to figure out what the function composition does than to write a loop vectorizer
I probably agree but complicated loop vectorisation would probably expressed in Einstein tensor contraction notation such as Tullio.jl provides. I wonder a Fourier transform would look using function decomposition.
@tullio F[k] := S[x] * exp(-impi/8 (k-1) * x) (k ∈ axes(S,1))
Maybe a new iteration construct specifically supporting parallelization would help here. Some of these things might already work quite well, for example it should not be difficult to discern from (let me use ITERATE's example)
(iterate (for el in list)
(finding el minimizing (length el)))
that you're computing argmin using a pure function, which should be easy to do in parallel, whereas the way you'd typically write this in C would be probably difficult for the compiler to confirm as such (it would have to look for pattern such as "if (f(current)<f(best)) { best=current; }" or something like that. (BTW have you seen another loop construct supporting argmin/argmax in another language? I haven't so far.) Whether this could be done somewhat generally and extensibly is something I have to ponder on.That's true in many situations, but in this case the equivalence between the two is so straightforward that I can't see recursion gaining you any clarity. Perhaps you have a concrete example?
Sometimes it makes more sense and is more flexible to package functionality as a recursive function, then mutation and variables feel like clutter. Other sometimes using recursion instead of a loop gains nothing expressively. Or sometimes structural recursion + pattern matching is the much more elegant approach in terms of communicating and capturing the essence of the algorithm.
If your language of choice features formalized modules in the Modula-2 sense, its loops most likely can't span multiple functions even within a single Modula-2-sense module, even if you wanted that (for example, in a state machine with named states as functions which tail-call each other to switch state by transferring control, or something like that).
https://github.com/TakekazuKATO/TailRec.jl
It works by inspecting the code and rewriting a function to turn tail calls into loops.
The interesting bit is that it was very easy to write because of the strong macros in Julia.