Or, if you want Guy Steele's opinion, every call is essentially a goto and should be treated as such. Thinking about function calls as graph traversal instead of a call stack allows you to do any call without any unnecessary variables.
The first comment is right though that he missed much of the nuances of C calling conventions, which I first thought this article was about. Still, it's much more interesting the way it turned out, a very good introduction to many interesting techniques that I wasn't aware of (and of which I'm not convinced of their usefulness, but still...)
Missed things like overloading in C++ (calling different functions by matching of their type signature, not just their name), template functions, generics, and exception handling (try/catch/throw).
In his summary of tail call optimization, he doesn't make it clear that TCO is especially useful with mutually recursive functions. If you have eight different functions that tail call to each other (in a state machine, say), you can still do so in constant space. Doing that without TCO usually leads to inlining every state's code, and then a big switch statement or lots of GOTOs.
Tail-call optimization makes function calls more expressive. THAT's why they matter.
Any complaining that they lose debugging info strikes me as a bit weird. So do for / while loops, and leaf calls in procedures. So what? If you need logging, add logging.
One might need to know considerably more, especially for low-level coding and/or efficiently SSE use. Recently we've had occasion to figure out quite a bit about stack usage and this yielded some surprises; I suspect that gcc could still use some work in conserving stack space.
As a grad student, in the dark days of the mid-90s we found a obscure and nasty hole in the MIPS calling conventions as they existed then, where IIRC you could actually lose a floating point parameter when making a variadic call.
It required a particular combination of not having ANSI headers and using a float vs. double in just the wrong place, and was more of a theoretical curiosity (again, if I remember correctly, you needed to be the float or double as the first arg to a variadic function, which is unlikely, as typically variadic functions take structs or pointers telling them what they'll be doing as their first arg).
Shortly after Bailey and Davidson published a paper that found the one we found, and a bunch of others, although these also included a lot of implementation flaws that weren't inherently holes in the convention per se:
6 comments
[ 4.5 ms ] story [ 19.9 ms ] threadhttp://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-...
Tail-call optimization makes function calls more expressive. THAT's why they matter.
Any complaining that they lose debugging info strikes me as a bit weird. So do for / while loops, and leaf calls in procedures. So what? If you need logging, add logging.
As a grad student, in the dark days of the mid-90s we found a obscure and nasty hole in the MIPS calling conventions as they existed then, where IIRC you could actually lose a floating point parameter when making a variadic call.
It required a particular combination of not having ANSI headers and using a float vs. double in just the wrong place, and was more of a theoretical curiosity (again, if I remember correctly, you needed to be the float or double as the first arg to a variadic function, which is unlikely, as typically variadic functions take structs or pointers telling them what they'll be doing as their first arg).
Shortly after Bailey and Davidson published a paper that found the one we found, and a bunch of others, although these also included a lot of implementation flaws that weren't inherently holes in the convention per se:
http://www.cs.virginia.edu/~mwb5y/pubs/pldi96.pdf