For those wondering about the "tail call" part that would be more interesting for Clojure than fibers:
As adding the ability to manipulate call stacks to the JVM will undoubtedly be required, it is also the goal of this project to add an even lighter-weight construct that will allow unwinding the stack to some point and then invoke a method with given arguments (basically, a generalization of efficient tail-calls). We will call that feature unwind-and-invoke, or UAI.
It is not the goal of this project to add an automatic tail-call optimization to the JVM.
One issue to implement TCO is that the "security model"/circus of Java is based on the stack frames, so you can not remove stack frames without getting into trouble.
I interpret this as "we will add a primitive that will allow you to implement TCO yourself (and more), but the behavior of existing java or byte code won't change, and the stack will continue to grow, even if a call occurs in tail position". Presumably because it's hard to impossible to retrofit TCO without changing observable behavior.
Well, good points but I was rather thinking the compiler should do it as an option.
Of lesser note, I don't believe I've ever come across mutually tail recursive functions, or the need for them, and although that may reflect my lack of experience in some areas, I guess it's not at all common? Maybe in the haskell world perhaps.
They make state machines leagues easier to reason about. Each state is its own function, and you tail-call to the next state (and pass along only the data it relies on, if you're doing things functionally).
All flow control ultimately boils down to `goto`; it's how we crystallize particular usage patterns that makes it safer. Importantly, optimizing tail calls doesn't change the fact that you could always call another function before you return; you just risked blowing the stack.
I find that recursive solutions are often easier to understand and change than iterative solutions, especially because you need less incidental state (and you can manage the state you have more cleanly), so I'm not sure what you mean by "introducing complexity only to struggle to delete that complexity". That would more aptly describe my experience with writing iterative versions of naturally recursive algorithms.
(I think you may have mistaken me for someone else; I didn't recommend Steele's paper.)
If goto is easily available in the high level language then creating a state machine is trivial I guess. If it's not then the compiler should be able to do TCO with jumps/gotos in the output asm or transpiled code (IIRC Bison's output uses gotos even though the input yacc rules clearly have none).
> If goto is easily available in the high level language then creating a state machine is trivial I guess.
It's still painful, because whichever state you're in probably cares about different data. Some data only needs to exist during some states. Factoring states into separate functions means each gets its own scope, and can explicitly pass only data needed for the next state forward.
> If it's not then the compiler should be able to do TCO with jumps/gotos in the output asm or transpiled code
It's nice to be able to indicate explicitly to the compiler (and other developers!) that you expect tail calls to be optimized, rather than crossing your fingers and hoping that nobody else comes along later and accidentally adds something after the call. Scala optimizes tail recursion by default, but it also has a `tailrec` annotation that causes the compiler to throw an error if it isn't able to respect that intent.
> I don't believe I've ever come across mutually tail recursive functions, or the need for them
Well, had you read the link I posted in my reply to your question, you would have ;) Anyway, there are a some useful things that are much harder to do pleasantly and efficiently without it.
Tail-call optimisation on the JVM is already somewhat supported with an annotation / keyword (depending on language). My understanding is that the project will improve the current implementation, but you'll still need to define when a function is tail-recursive, the compiler won't do it automatically.
Unless something changed since 2.0.9 (last time I did anything relevant in Scala), only one level, it isn't clever enough to rewrite mutually recursive calls.
This is rather important, specially when coming from languages like Scheme that have TCO as part of the language specification compliance.
No we won't. [1] does not even mention tail-call elimination. Project Loom does not change the bytecode and does not change it's semantics. I.e. we don't get guaranteed tail-call elimination.