Re: Problems with CPS'ing python functions

Tim Peters (tim@ksr.com)
Fri, 27 May 94 15:25:36 -0400

> [steve, wants to do the scheme
>
> (define fact-cps
> (lambda (n k)
> (if (zero? n)
> (k 1)
> (fact-cps (- n 1)
> (lambda (v) (k (* n v)))))))
>
> in python; the python attempts trigger NameError]
> ...
> From what I can gather, the local functions cps (in factcps2) and the
> lambda (in factcps) are unable to access the environment of factcps2
> and factcps, respectively.

Right, & see question 4.5 of the Python FAQ for a start at an explanation.

> Any ideas on how to solve the problem?

There are sooooo many amusing snotty answers I _could_ give, I'll cut the
list a break and just give the answer you want <wink>:

def factcps(n, k):
if n == 0:
return k(1)
else:
return factcps( n-1,
lambda v, k=k, n=n: k(n*v) )

from whrandom import randint

print map( lambda n: (n, factcps(n, lambda m: m)),
map( lambda n: randint(0,n),
[10]*10
)
)

That (may) print

[(10, 3628800), (8, 40320), (9, 362880), (10, 3628800), (8, 40320), (0, 1),
(8, 40320), (4, 24), (5, 120), (4, 24)]

Alternatives to abusing the keyword-argument device are to make all
arguments to the "continuation" function explicit, hide info in classes,
or write fac with a loop like God intended <snort>.

on-your-own-for-call/cc-though-that-one-caught-god-by-surprise-ly y'rs
- tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp