As usual, it seemed to be useful for at least one person (myself), so Continuation-passing style (CPS) for each language. The sample description of is summarized as an article.
In interactive mode, substitute 10 for x
and then let x + 20
be evaluated.
>>> x = 10
>>> x + 20
30
When I make this program description into a file and let the Python interpreter execute it, nothing is displayed. This is because in the interactive mode (REPL), the result evaluated as an expression is displayed, whereas in the file execution (script), such a display is not performed.
C:\Users\hoge>type sample.py
x = 10
x + 20
C:\Users\hoge>python sample.py
C:\Users\hoge>
If you want to display the evaluation result by executing the file, you need to display it using, for example, print
after obtaining the evaluation result.
C:\Users\hoge>type sample.py
x = 10
print(x + 20)
C:\Users\hoge>python sample.py
30
C:\Users\hoge>
Here, when describing as an expression, consider a mechanism in which a function that processes the evaluation result must be specified. The following is an example of defining a function cadd20
that is called by passing the evaluation result as an argument to the function f
after evaluating x + 20
, and specifying print
for f
. ..
C:\Users\hoge>type sample.py
def cadd20(x, f): f(x + 20)
x = 10
cadd20(x, print)
C:\Users\hoge>python sample.py
30
C:\Users\hoge\python>
In this way, the programming method that assumes a mechanism to specify the procedure for processing the result in advance is "[Continuation-passing style](https://ja.wikipedia.org/wiki/%E7%B6%99%]. E7% B6% 9A% E6% B8% A1% E3% 81% 97% E3% 82% B9% E3% 82% BF% E3% 82% A4% E3% 83% AB) ”(continuation-passing style, CPS ). This style has been applied to various implementations, including unconscious forms.
try
(procedure to call) and ʻexcept` (procedure to specify)It is easy to convert a function to CPS, but some ingenuity is required to use the converted function. Here, the conversion of an existing function to CPS and an example of its use are shown (the main body of this cheat sheet).
from operator import add, sub, mul
# func(x, y) = (x + y) * (x - y)
def func(x, y): return mul(add(x, y), sub(x, y))
print(func(10, 20)) # => -300
def cps(f):
def cps(x, y, c): return c(f(x, y))
return cps
cps(add)(10, 20, print) # => 30
def cfunc(x, y, c):
return cps(add)(x, y, lambda c1: # x + y -> c1
cps(sub)(x, y, lambda c2: # x - y -> c2
cps(mul)(c1, c2, c))) # c1 * c2 -> c
cfunc(10, 20, print) # => -300
Scheme(Gauche,Guile)
; func(x, y) = (x + y) * (x - y)
(define (func x y) (* (+ x y) (- x y)))
(display (func 10 20)) ; => -300
(define (cps f) (lambda (x y c) (c (f x y))))
((cps +) 10 20 display) ; => 30
(define (cfunc x y c)
((cps +) x y (lambda (c1) ; x + y -> c1
((cps -) x y (lambda (c2) ; x - y -> c2
((cps *) c1 c2 c)))))) ; c1 * c2 -> c
(cfunc 10 20 display) ; => -300
Ruby(CRuby)
# func(x, y) = (x + y) * (x - y)
def func1(x,y) (x+y)*(x-y) end
p func1(10,20) # => -300
add = -> x,y { x+y }
sub = -> x,y { x-y }
mul = -> x,y { x*y }
prn = -> x { p x }
cps = -> f { -> x,y,c { c.(f.(x,y)) } }
cps[add][10,20,prn] # => 30
cfunc = -> x,y,c {
cps.(add).(x, y, -> c1 { # x + y -> c1
cps.(sub).(x, y, -> c2 { # x - y -> c2
cps.(mul).(c1,c2,c) }) }) # c1 * c2 -> c
}
cfunc[10,20,prn] # => -300
JavaScript(Node.js)
// func(x, y) = (x + y) * (x - y)
function func1(x,y) { return (x+y)*(x-y) }
console.log(func1(10,20)) // => -300
add = (x,y) => x+y
sub = (x,y) => x-y
mul = (x,y) => x*y
cps = f => (x,y,c) => c(f(x,y))
cps(add)(10,20,console.log) // => 30
cfunc = function(x,y,c) {
return cps(add)(x, y, c1 => // x + y -> c1
cps(sub)(x, y, c2 => // x - y -> c2
cps(mul)(c1,c2,c))) // x * y -> c
}
cfunc(10,20,console.log) // => -300
call / cc
usage example (from Twitter comment)Recommended Posts