Earlier quoted context omitted.
Sounds similar to @tailrec in Scala I personally use the phrase "tail call elimination" when it's a requirement that can be relied on; and "tail call optimisation" when it might be implementation-dependent, context-dependent, limited (e.g. to immediate self-calls), etc.
I am definitely not a Scala expert. As I wrote in a sibling comment, the key benefit here is the extra work from the compiler to deliver what you wanted, on top of the diagnostic if it can't. I don't know if Scala has the problem that `become` addresses (C++ calls this RAII, but I have no idea what Scala would call it if they have the same idea) However in my brief attempt to validate what Scala does do here, I found…
Tail-call optimization in C is relatively recent (2025)
71–80 of 144 posts
Re: Tail-call optimization in C is relatively recent (2025)
#72Earlier quoted context omitted.
I am not a Clang expert, but first, obviously that's a C++ attribute and so while Clang can decide what it means in Clang in the programming language itself it has no semantic weight because the ISO document says attributes are always ignorable. Secondly however in these languages you often won't naively get TCO because you have at least one local variable which C++ would say has a "non-trivial destructor" or Rust wo…
Clang tail-calls aren't guaranteed to work with all C++ code. If you have a non-trivial constructor, as you mention, it will tell you this and fail instead of silently letting you believe you have tail-calls when you don't.
Re: Tail-call optimization in C is relatively recent (2025)
#73Earlier quoted context omitted.
Js really should have it. I think the shift in style from functional and manual prototype chains to Java classes is quite disappointing.
ES6 class syntax is still mostly just syntax sugar overtop prototypical inheritance. JS _does_ still have TCO (called Proper Tail Calls), Safari's JavaScriptCore implements it, and is technically the only conforming interpreter.
I can’t rely on TCO if chromium doesn’t have it.
Re: Tail-call optimization in C is relatively recent (2025)
#74Earlier quoted context omitted.
They officially saw no need for C support going forward. https://herbsutter.com/2012/05/03/reader-qa-what-about-vc-an... Note, "If you really need either of the following.....then we recommend that you consider using a different compiler such as Intel or gcc (short-term) and/or pressure your standards committee representatives to have ISO C++ include more of the C standard (longer-term)." Which is kind of why nowaday…
TIL, thanks for updating me on this! I read Herb Sutter’s post many years ago, but didn’t know they had picked up the work again. I see that VLAs are still not supported, which is a shame IMO, but the C-support seems much better than it used to be at least.
If C23 ever comes to land on MSVC, which I have my doubts given the radio silence on C support, I assume they might add the VLAs part that made it again back into C23.
Re: Tail-call optimization in C is relatively recent (2025)
#75Earlier quoted context omitted.
It's hard to argue that it isn't an optimization, because it doesn't affect the semantics of the program. However most optimizations are very hard to observe. The vast majority of optimizations only affect code size and runtime. TCO is one of the few exceptions. It affects memory usage, and more sensitive stack memory at that. This is why a missed optimization can be so much more catastrophic and it is worth consider…
If the semantics of 'while (true)' was "will crash the program after an implementation-defined but often fairly low number of iterations", I would stop using 'while (true)'.
Re: Tail-call optimization in C is relatively recent (2025)
#76Earlier quoted context omitted.
It's hard to argue that it isn't an optimization, because it doesn't affect the semantics of the program. However most optimizations are very hard to observe. The vast majority of optimizations only affect code size and runtime. TCO is one of the few exceptions. It affects memory usage, and more sensitive stack memory at that. This is why a missed optimization can be so much more catastrophic and it is worth consider…
If my program crashes without it, that's a semantic difference no?
Re: Tail-call optimization in C is relatively recent (2025)
#77Earlier quoted context omitted.
Not every tail call is for a loop. You can have a set of mutually recursive functions, which tail call each other. In C you can write state machines using "goto" (the implementations with "switch" are typically much more inefficient), but in languages with guaranteed tail call optimizations you can write a state machine where each state is a function. In general, it is frequent enough to call another function as the…
I can't see why the calling convention could matter. Can you give an example?
Re: Tail-call optimization in C is relatively recent (2025)
#78Earlier quoted context omitted.
If the semantics of 'while (true)' was "will crash the program after an implementation-defined but often fairly low number of iterations", I would stop using 'while (true)'.
It’s precisely not the semantics of the program that will crash the program, but the behavior of the language implementation. It’s similar to when a program in a GC language fails with OOM because the language implementation uses a no-op collector. That’s usually not part of programming language semantics.
Re: Tail-call optimization in C is relatively recent (2025)
#79What practical patterns are enabled by TCO in C? My impression is that every tail call can written as a loop much more naturally. Tail calls are important in functional languages where you don't have mutable loop variables. And imo they are an ugly hack even there - one of the few core constructs where its readily apparent you're not programming an abstract machine but a real, and limited computer. For example the mo…
local factorial do
local function impl(n, acc)
if n == 1 then
return acc
else
return impl(n - 1, acc * n)
end
end
factorial = function(n)
if n
You could replace impl with an imperative loop: local acc = 1
repeat
acc = acc * n
n = n - 1
until n == 1
return acc
Personally, I find this ugly compared to the tail recursive solution. The loop version only seems more natural if you primarily think in loops. Tail recursion is strictly more powerful than looping since every imperative loop can trivially be converted to a tail recursive function, but the reverse is not true.Re: Tail-call optimization in C is relatively recent (2025)
#80Earlier quoted context omitted.
I can't see why the calling convention could matter. Can you give an example?
When the calling convention is such that the caller owns the function arguments, the callee can’t remove/replace them on the stack, but has to keep them across the tail call. In turn, it means that the callee has to clean up the arguments to the tail call, and thus can’t actually make a tail call, unless the argument list happens to be identical to the original call.