Nathan,

On 8 September 2015 at 15:58, Thomas Koster <[email protected]> wrote:
> F# appears to eliminate tail calls to self by program transformation
> where it is trivial to do so, but relies entirely on the CLR for
> optimizing tail calls in general. This would mean that the stability and
> reliability of programs written for the CLR in F# is uncertain, and that
> debug builds of F# programs are always unreliable. I would want much
> stronger guarantees about space complexity if I were to seriously
> consider F# as a programming language for paid work.
>
> So if anybody has used F# in the real world, what's the story?

On 14 September 2015 at 18:06, Nathan Schultz <[email protected]> wrote:
> IIRC, as you said, for most tail-end recursion, you'll find that the IL that
> F# generates is actually a simple loop with a mutable variable. In cases
> where there's continuations involved or more complex scenarios with multiple
> recursive functions, F# will automatically provide the CLR with the .tail
> instruction. Work has gone into the CLR to better support tail end
> recursion, and there have been lots of fixes in recent versions (e.g. going
> back a couple of years, there used to be scenarios where the JIT would
> ignore the flag, but have been fixed).
>
> I've never run into an issue myself, although infrequently I have heard of
> corner-cases that still pose issues (e.g.
> http://blogs.msdn.com/b/dotnet/archive/2015/07/28/ryujit-bug-advisory-in-the-net-framework-4-6.aspx).
> However, I've also heard it said that when it comes to tail-end recursion F#
> is in a better place with the CLR than Scala is with the JVM. And both are
> used in production even in financial institutions.
>
> Given that I (rarely) still run into other bugs in the .Net framework with
> C#, I don't see this as anything different; testing (including on different
> platforms) is a necessary part of application development, and with F# it's
> no different.

Thanks for your response.

I readily believe that the JVM is a worse place for functional languages
than the CLR. But both seem to share the same weakness when it comes to
implementing functional languages: they both support only one evaluation
strategy, namely the stack-based, strict, call-by-value evaluation
strategy of the curly brace langauges (and their predecessors). The
opcodes needed to implement other strategies efficiently are missing.

I am starting to see that I may have over-estimated the number of ways
space leaks caused by tail calls can creep into an F# program. But since
F# uses a strict evaluation order where tail call elimination is
absolutely necessary to avoid excessive space usage, the discretionary
nature of the ".tail" opcode prefix still makes me uneasy and I would
rather not have to write tests to verify the correctness of the F#
compiler, let alone the JIT compiler.

So for now, for me, F# remains just an intellectual curiosity.

--
Thomas Koster

Reply via email to