>>19The conditional isn't part of the tail call, just like it isn't part of any other non-tail call! How the fuck do you think you make conditional function/procedure/method calls in any other language?
The only difference with tail recursion is it GOTOs back to the start of the function, rather than to a new function or establishing a new stack frame. Fuck, it's even more gimped than GOTO because you can't even specify a god damned label
!>>18Lol, looking into disassemblies in Racket scheme, which I do use on occasion, and googling around it looks like Scheme implementers are still using fucking continuation thunks to tail recurse. What a fail language. Show me a scheme compiler that can actually fucking compile, and I'll point you straight to the GOTO/JMP. Even the most simple infinite loop tail recursion pops out to continuation thunks, even though it's 100% statically provable that there will never be any continuation escaping.
The only thing a tail recursion is conceptually is a GOTO back to the beginning of the function. It's a failure of Scheme and its ultra-shitty call/cc
Fine, show me a scheme compiler that actually compiles decently and gives disassemblies and I'll point it out to you. I have racket, but its output is bullshit. It thunks through tail calls like Java hacks do it, even though
I'll entertain you, you brainless piece of shit with your fucking clueless nigger intellect.
I have Racket, but it does not generate tight asm code at all. Sifting through all its bullshit, let's look at the basic fucking factorial:
(define (factorial x accum)
(if (zero? x)
acc
(factorial (sub1 x) (* x accum))))
This generates 124 fucking lines of asm, with zero commenting on the bullshit non-inline utility callouts it makes, or the memory locations of its variables, whereas the obviously superior Common Lisp (SBCL) makes a very readable 32 asm instructions for the fully generic version, and down to 13 if the numbers are declared to be fixnums:
CL-USER> (disassemble #'factorial)
; disassembly for FACTORIAL
; Size: 33 bytes. Origin: #x1006AF63C0
; C0: L0: 4885C9 TEST RCX, RCX ; no-arg-parsing entry point
; C3: 7506 JNE L1 <<= Go do the work if x isn't zero
; C5: 488BE5 MOV RSP, RBP
; C8: F8 CLC
; C9: 5D POP RBP
; CA: C3 RET <<= Exit if RCX up there was zero
; CB: L1: 488BD9 MOV RBX, RCX
; CE: 4883EB02 SUB RBX, 2 <<= Subtract 1, shifted past the tag bit means an immediate 2
; D2: 48D1F9 SAR RCX, 1
; D5: 480FAFCA IMUL RCX, RDX <<= Multiply
; D9: 488BD1 MOV RDX, RCX
; DC: 488BCB MOV RCX, RBX
; DF: EBDF JMP L0 <<= GOTO FUCKING START OF FUNCTION
It can do this because there isn't this low level intrusive BULLSHIT of call/cc fucking up anything that anybody might ever want to do, even though nobody in their right mind in real applications ever touches call/cc. Just like people dick around with pure functional cons list processing in Lisp academically but use actual data structures in the Real World, call/cc is just academic hackery fuckings that kids are forced to dick around with in class that nobody uses in the few cases of Real World Scheme. Yet its presence fucks over the Scheme implementors, whereas functional cons processing doesn't affect Common Lisp one way or another.
Maybe Stalin does this properly, as its docs say "3. (1.1) Tail recursion optimization is done only on self calls." which would also imply no need for continuation escape analysis, and that static constraint would allow it to compile to a JMP. But I'll leave that as an exercise for the reader, meaning I'm not going to pile into unfamiliar territory just to make a point that's already self-evident.
But in any case, tail recursion IS a GOTO to the beginning of the function. The fact that Scheme is a shitty language and needs to do laughable workarounds at the assembly level to get GOTO to work happens to obscure that primitive fundamental axiomatic fact. Or taken differently, the bullshit in Scheme means it cannot ACTUALLY perform tail recursion optimization. It still fits in a static memory footprint, but cannot actually optimize the conceptual GOTO into a real GOTO in hardware and needs to jump out and back in to perform a simple GOTO. By definition, actual tail recursion is never NOT a GOTO, regardless of how you have to make that GOTO happen, and regardless that your idiot Scheme implementors can't detect situations where the context does not need to exit to loop back.
IHBT