Use the tco package to perform factorial calculations through tail call optimization

I try to use the tco package [1] to perform factorial calculations through tail call optimization, as follows:

from tco import *

@with_continuations()
def factorial(n, k, self=None):
    return self(n-1, k*n) if n > 1 else k

print(factorial(5,1))

The above code works, but the following one doesn’t:

from tco import *

@with_continuations()
def factorial(n, k):
    return factorial(n-1, k*n) if n > 1 else k

print(factorial(5,1))

When I run it, the following error will be triggered:

File "/home/werner/untitled-1.py", line 12, in <module>
  print(factorial(5,1))
File "/home/werner/.pyenv/versions/datasci/lib/python3.9/site-packages/tco/__init__.py", line 41, in __call__
  return f(*args)
File "/home/werner/.pyenv/versions/datasci/lib/python3.9/site-packages/tco/__init__.py", line 86, in <lambda>
  f(*args, self=kself, **dict(zip(keys, conts)))) (*k)

builtins.TypeError: factorial() got an unexpected keyword argument 'self'

I’m not so familiar with decorator. Any hints/explanation will be highly appreciated.

[1] GitHub - baruchel/tco: Tail Call Optimization for Python

Regards,
HZ

You should read the documentation for the tco package:

Your second example fails because the with_continuations decorator
requires the function to use a parameter called “self”. The
documentation says:

“The self keyword is mandatory for all decorated functions; it can be
used in the body of the function for a tail-recursive call.”

If you leave out the self keyword, the with_continuations decorator will
fail when you call the function.

You cannot use the with_continuations decorator on any arbitrary
function. It must be used with functions that are written in
continuation-passing style (CPS), and it must use self as the
continuation parameter. These are hard requirements.

Continuations are an advanced, and complex, technique from functional
programming style, and it is difficult to find a good explanation for
how they work aimed at beginners.

If anyone knows of a good explanation of CPS aimed at beginners, one
that doesn’t just sketch a vague, handwavy explanation and then leave
four fifths of the details to “fun exercises” like re-writing the
node.js server code to make it work (!!!), I would appreciate the link.

https://matt.might.net/articles/by-example-continuation-passing-style/

Do you mean the explanation from this linked article is a good explanation of CPS aimed at beginners?

No. The linked article is another example of a bad explanation of CPS
aimed at beginners.

But don’t take my word for it, read it. Maybe it will make more sense to
you than it makes to me.

If so, why you still said: “I would appreciate the link”?

Thank you again. I really learned something from the linked article, say the idea implied in the following code snippet:

function fact(n,ret) {
  if (n == 0)
    ret(1) ;
  else
    fact(n-1, function (t0) {
     ret(n * t0) }) ;
}

And, to "use" the function, we pass it a callback:
fact (5, function (n) { 
  console.log(n) ; // Prints 120 in Firebug.
})

But BTW, I want to find a convenient REPL for javascript, just like ipython I use for python, but still I can’t such a powerful can convenient one. Do you have any recommendations?

Regards
HZ

I said I would appreciate the link because I would like to read a good,

basic, simple explanation of CPS suitable for beginners. If you have a

link to a good, basic, simple explanation, I would like to see a link to

that explanation.

All the explanations I have read are not good, basic or simple.

As for a convenient REPL for Javascript:

If you find one you like, let us know.

The following one is wonderful and support so many languages including javascript, but it must be used online:

https://replit.com/languages/JavaScript

And it also supplies a free plan for starter level which is enough for testing and learning:

Another possibility is to use Emacs for JavaScript development. I found the following great guidelines:

http://wavesurfer-js.org/blog/emacs-javascript.html

Regards,
HZ