34 (2017 ) CPS 1 or while 1 1. 2. 3. 2 On optimization or recursive programs without tailcalls. Shutaro Kobayashi, Hideyuki Kawabata, and Tetsuo Hironaka,, Hiroshima City University. 1 2 https://www.quora.com/why-dont-pureunctional-programming-languages-provide-aloop-construct 1. 2. OCaml goto [16] [15] [14] 3 Scheme[13] do 3 [14] map old
[14] OCaml 4 Continuation-Passing Style (CPS) 1. 2. 3. old [9] 5 5 2 4 OCaml 5 OCaml 2. 1 sum n = n i=0 i let rec sum n = i n = 0 then 0 else n + sum (n-1) # sum 3 ;; - : int = 6 # sum 300 ;; - : int = 45150 # sum 300000 ;; Stack overlow during evaluation (looping recursion?). # 16GB 3.3GHz 0 300000 2. 2 let rec sum n a = i n = 0 then a else sum (n-1) (n+a) # sum 300000000 ;; - : int -> int = <un> # sum 300000000 0 ;; - : int = 45000000150000000 # 0 300000000 2. 3 [1] n m upto
lsum n m sum let sum n m = lsum (upto n m) let sum n m = List.old_right (+) (upto n m) 0 upto upto upto # List.old_right (+) (upto 0 300000) 0;; Stack overlow during evaluation (looping recursion?). upto # List.old_let (+) 0 (upto 0 300000);; - : int = 45000150000 # let upto n m = let rec iter n m a = i n >= m then a else iter n (m-1) (m::a) in iter n m [] # let l = upto 0 300000 ;; Stack overlow during evaluation OCaml (looping recursion?). List.map List.old right # let l = upto 0 300000 ;; val l : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10;...] # lsum # lsum (upto 0 300000) ;; Stack overlow during evaluation (looping recursion?). 3 # lsum (upto 0 300000) ;; - : int = 45000150000 # 3. 1 let rec loop arg = i is_inal arg then r arg else (d1 arg) (loop ( arg)) 1 2. d1 arg (d1 (d1 (d1 (r n 2 (d1 n n 1 1. 2 6 oldr/build hylo usion [8] [17]
3. 2 3. 3 3. 4 3. 5 3. 6 3. 1 1 1 arg old 1 2 i i = 1, 2, loop (d1 {{ i 1 i loop is inal (( {{ ) = true i 1 d1 arg is inal r d1 arg 1 is inal r d1 1 loop 2. 1 sum int int is inal = un x x = 0 r = un x x d1 = un x x = un x x 1 = un x y x + y loop α list int is inal = un x x = [ ] r = un x 0 d1 = un x 1 = un x List.tl x = un x y x + y loop (n, m) n m n m int * int int is inal = un (n, m) m = 0 r = un (n, m) 1 d1 = un (n, m) n = un (n, m) (n, m 1) = un x y x y loop (l 1, l 2) l 1@l 2 α list * α list α list is inal = un (l1, l2) l1 = [ ] r = un (l1, l2) l2 d1 = un (l1, l2) List.hd l1 = un (l1, l2) (List.tl l1, l2) = un x y x::y loop n > 0 n n 1 int int * int is inal = un n n = 1 r = un n (1, 1) d1 = un n (1, 1, 1, 0) = un n n 1 = un (x, y, z, w) (p, q) (x p + y q, z p + w q) 2 2 2 2 r 1 (1, 1, 1, 0) (p + q, p) loop
let rec loop arg k = i is_inal arg then k (r arg) else loop ( arg) (un x -> k ( (d1 arg) x)) 3 CPS α * α list α list is inal = un (e, l) l = [] e < List.hd l r = un (e, l) i l = [] then [e] else (e::l) d1 = un (e, l) List.hd l = un (e, l) (e, List.tl l) = un h t h::t loop (n, m) int * int int is inal = un (n, m) m = 0 r = un (n, m) n d1 = un (n, m) 0 = un (n, m) (m, n mod m) = un x y y loop n a n+1 2a n 2n + 3 = 0, a 0 = 4 n a n int int is inal = un n n = 0 r = un n 4 d1 = un n 2 n 3 = un n n 1 3. 2 CPS = un x y x + 2 y 1 loop 7 loop CPS CPS 7 3. 1 loop let rec loop arg acc = i is_inal arg then old_let (un x y -> y x) (r arg) acc else loop ( arg) ((d1 arg) :: l) 4 (d1 i i i s n (d1 i i s n 1 (d1 i i s (r s (d1 i s 5 1 loop CPS 3 3. 1 1 3 un x x CPS 1 d1 arg, (d1, (d1, 3 3. 3 1 4 old 3. 1 1 4 3. 4 2 old m
let loop arg = let d = s arg in let p = is_inal_i (i arg) in let rec loop a acc = i p a then acc else loop (i a) ( (d1 a) acc) in loop (i d) (r d) 6 (r n (d1 d1 arg (d1 n 1 er 7 {{ arg O(m) m i s 2 5 s = {{ n 5 6 3. 1 1 6 is inal i i s 6 loop 2. 1 sum int int is inal i = un x y x = y i = un x x + 1 s = un x 0 6 loop (n, m) n m n m int * int int is inal i = un x y x = y i = un (n, m) (n, m + 1) s = un (n, m) (n, 0) 6 loop n > 0 n n 1 let loop arg = let rec loop a acc = i is_inal a then ( acc (r a)) else loop ( a) ( acc (d1 a)) in loop arg er 8 int int * int is inal i = un x y x = y i = un n n + 1 s = un n 1 6 loop n a n+1 2a n 2n + 3 = 0, a 0 = 4 n a n int int is inal i = un x y x = y i = un n n + 1 s = un n 0 3. 5 a ( b c) = ( a b) c a er a = a er 2 7 8 3. 1 1 8 er = 0 8 loop 2. 1 sum int int er = 0 8 loop α list int er = 1 8 loop
(n, m) n m n m int * int int er = 0 8 loop (n, m) int * int int 3. 6 3. 1 3. 2 3. 3 d1 3. 4 3. 5 3. 1 d1 3. 1 2 2 3. 5 d1 2 5 7 = un x x old 2 d1 is spec 3. 4 3. 5 9 type ( a, b, c) pr_spec = { is_inal: a -> bool; r: a -> b; d1: a -> c; : a -> a; : c -> b -> b let genpr_spec spec = let rec loop arg = i spec.is_inal arg then spec.r arg else spec. (spec.d1 arg) (loop (spec. arg)) in loop let sum_spec = { is_inal = (un i -> i = 0); r = (un s -> s); d1 = (un x -> x); = (un x -> x - 1); = (un x y -> x + y) let sum = genpr_spec sum_spec 1 4 3. 1 9 OCaml 4.05.0 ocamlopt 3.3GHz Core i7 16GB macos 10.12.6 OCaml Sys.time 1 1 9 1 CPS 3 4
1 1 3 CPS 4 6 8 0.78 4.20 (5.4) 2.94 (3.8) 0.72 (0.9) 0.72 (0.9) 0 10 1000 1.03 5.87 (5.7) 3.32 (3.2) 0.64 (0.6) 10 1000 0.28 0.34 (1.2) 0.34 (1.2) 0.79 (2.8) 0.28 (1.0) 3 30 100 8.58 13.66 (1.6) 7.69 (0.9) 10 2 1000 0.79 1.01 (1.3) 0.98 (1.2) 0.77 (1.0) ib 100 100 3.02 5.74 (1.9) 3.23 (1.1) 10 1000 0.09 0.10 (1.1) 0.10 (1.0) 0.08 (0.9) gcd(51,100) 100 0.37 0.48 (1.3) 0.47 (1.3) 0.38 (1.0) 50 100 Sys.time 3, 4, 5, 6 2 3. 1 3 9 100 5 old map [1] [15] [5] [3] deorestation [18] [18] oldr/build [8][12] hylo usion [17] oldr/build [10][4] [11] [9] [9] hylomorphism [8] [4] [21] [11] [6] [19] [2][7] hylo usion [20] [22] 6
17K00106 [ 1 ] Bird, R.: Pearls o Functional Algorithm Design, Cambridge University Press,,,, 2014 edition, 2010. [ 2 ] Bird, R., de Moor, O., and Hoogendijk, P.: Generic programming with relations and unctors, Journal o Functional Programming, Vol. 6, No. 1, pp. 1 28, 1996. [ 3 ] Burstall, R. M. and Darlington, J.: A Transormation System or Developing Recursive Programs, Journal o the ACM, Vol. 24, No. 1, pp. 44 67, 1977. [ 4 ] Chitil, O.: Type Inerence Builds a Short Cut to Deorestation, ICFP 99, 1999. [ 5 ] Darlington, J. and Burstall, R. M.: A system which automatically improves programs, Acta Inormatica, Vol. 6, No. 1, pp. 41 60, 1976. [ 6 ] Fokkinga, M. M.: Law and Order in Algorithmics, PhD Thesis, Dept. In. University o Twente, 1992. [ 7 ] Gibbons, J.: Generic Downwards Accumulations, Science o Computer Programming, pp. 37 65, 2000. [ 8 ] Gill, A., Launchbury, J., and Peyton Jones, S. L.: A short cut to deorestation, FPCA 93 Proceedings o the conerence on Functional programming languages and computer architecture, 1993. [ 9 ] Hu, Z., Iwasaki, H., and Takeichi, M.: Deriving structural hylomorphisms rom recursive deinitions, ICFP 96 Proceedings o the irst ACM SIG- PLAN international conerence on Functional programming, pp. 73 82, 1996. [10] Launchbury, J. and Sheard, T.: Warm Fusion: Deriving Build-Catas rom Recursive Deinitions, FPCA 95 Proceedings o the seventh international conerence on Functional programming languages and computer architecture, pp. 314 323, 1995. [11] Németh, L.: Catamorphism-Based Program Transormations or Non-Strict Functional Languages, PhD Thesis, University o Glasgow, 2000. [12] Sheard, T. and Fegaras, L.: A Fold or All Seasons, FPCA 93 Proceedings o the conerence on Functional programming languages and computer architecture, pp. 233 242, 1993. [13] Shinn, A., Cowan, J., and Gleckler, A. A.(eds.): Revised 7 Report on the Algorithmic Language Scheme, 2013. [14] Shivers, O.: The Anatomy o a Loop: A story o scope and control, ICFP 05, 2005. [15] Steele Jr., G. L.: Debunking the Expensive Procedure Call Myth, AI Memo 443, MIT AI Lab, 1977. [16] Steele Jr., G. L. and Sussman, G. J.: LAMBDA: The Ultimate Imperative, AI Memo 353, MIT AI Lab, 1976. [17] Takano, A. and Meijer, E.: Shortcut Deorestation in Calculational Form, FPCA 95 Proceedings o the seventh international conerence on Functional programming languages and computer architecture, 1995. [18] Wadler, P.: Deorestation: Transorming programs to eliminte trees, Theoretical Computer Science, Vol. 73, pp. 231 248, 1990. [19] :,, Vol. 15, No. 6, pp. 57 70, 1998. [20],, :,, Vol. 17, No. 3, pp. 2 19, 2000. [21],,, :,, Vol. 17, No. 3, pp. 81 85, 2000. [22] :, 33, 2016.