tailcall(n)

πŸ“¦
version 9.0.3 Β· 2 versions
  • 9.0.3 Β· alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0 (latest)
  • 8.6.10 Β· centos-stream 9
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0

πŸ’« tailcall(n) πŸ’«

ok so this is a Tcl Built-In Command bestie, and it's genuinely one of the slayest little tricks in the whole interpreter. sit down, we're doing recursion the efficient way 🫢


✨ NAME ✨

tailcall β€” replace the current procedure with another command πŸ’…


🌸 SYNOPSIS 🌸

tailcall command ?arg ...?

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so here's the vibe: tailcall swaps out the procedure, lambda application, or method that's currently running and puts another command in its place. main character energy, honestly.

That command β€” and the arg ... you hand it, if you hand it any β€” gets looked up in the current namespace context, NOT in the caller's. that's the one lil plot twist. Apart from that difference in resolution, it is equivalent to:

return [uplevel 1 [list command ?arg ...?]]

and that's the whole thing fr fr. no cap. πŸŽ€

🚨 okay important caveat bestie: this command may not be invoked from within an uplevel into a procedure, or inside a catch inside a procedure or lambda. it's giving forbidden. don't do it. πŸ’€

πŸ”₯ EXAMPLE πŸ”₯

Compute the factorial of a number πŸ“

proc factorial {n {accum 1}} {
    if {$n < 2} {
        return $accum
    }
    tailcall factorial [expr {$n - 1}] [expr {$accum * $n}]
}

the way that tailcall just re-invokes itself and never grows the stack?? obsessed. periodt. ✨


proc printList {theList} {
    if {[llength $theList]} {
        puts "> [lindex $theList 0]"
        tailcall printList2 [lrange $theList 1 end]
    }
}
proc printList2 {theList} {
    if {[llength $theList]} {
        puts "< [lindex $theList 0]"
        tailcall printList [lrange $theList 1 end]
    }
}

look at them passing the baton back and forth like it's a relay race πŸ’– > then < then > then <… iconic behavior honestly.


πŸ‘‘ SEE ALSO πŸ‘‘


πŸ’œ KEYWORDS πŸ’œ

  • call
  • recursion
  • tail recursion

ok bye bestie, go write some stack-safe recursion and think of me πŸ’…βœ¨

Tcl 8.6 β€” tailcall(n) πŸŽ€ mwah, go slay 🫢

πŸ“¦ where this page comes from