Think about how, in a C-like language, the following two bits of code are completely equivalent:
if (cond1) { stuff1; } else { if (cond2) { stuff2; } else { if (cond3) { stuff3; } else { stuff 4; } } } | if (cond1) { stuff1; } else if (cond2) { stuff2; } else if (cond3) { stuff3; } else { stuff 4; } |
...except that the former is completely unidiomatic. What's unpleasant about it? The fact that you're getting textually more deeply nested with every else-if, which doesn't jibe somehow with the programmer's feelings about the code --- it feels rather like you're iterating down a linear list of conditions. I feel like I want to use the phrase "cognitive tail recursion". You're not requiring another brain-stack-frame to traverse each step of the process.
A language like perl that takes away your ability to leave off the braces around the branches of an if basically has to give you back a keyword like its elsif to save you from having to write code like on the left. I notice this because in supercollider, as far as I can tell, you do have to.
SML's if-then-else doesn't have any terminating token at all, so it is appropriately "cognitively tail recursive".
The way LISPs present lists to the programmer at all is the same. (1 . (2 . (3 . (4 . ())))) is the same value as (1 2 3 4) but we vastly prefer to look at the latter, flatter representation.
I want to think that this is all just a matter of actual, mechanical parsing; that it's just about an actual, literal tail recursive call going on in a parser, but I keep feeling there's something else interesting going here... Something about our intuitions about which textual operations/structures should be associative. Not coming up with anything concrete yet.