Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
TCO in CoffeeScript
tco = (fn) -> (args...) ->
if @recured? or @args? or @recur?
unless arguments.callee.noWarn
# here we are taking precautionary measures to make sure we don't
# accidentally overwrite some important properties in the context named
# "recured", "args" or "recur". The warnings can be disabled by setting
# the `noWarn` property of the function to true
throw new Error """
calling a tail-recursive function in this context will overwrite the
properties "recured", "args" and "recur".
"""
@recured = false
@args = []
@recur = (args...) =>
@recured = true
@args = args
returnVal = fn.apply this, args
while true
if @recured
tempArgs = @args
@args = undefined
@recured = false
returnVal = fn.apply this, tempArgs
else
return returnVal
#==============================================
factorial = tco (n, acc = 1) ->
if n is 0
acc
else
@recur n - 1, acc * n
console.log factorial 100000
#==============================================
factorialWithCtx = tco (n, acc = 1) ->
if n is 0
acc
else
@iterations++
@recur n - 1, acc * n
counter =
iterations: 0
console.log factorialWithCtx.call counter, 100000
console.log counter.iterations
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment