å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®1
å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話ãä½åãã«åãã¦ãã¾ãã
é£è¼ç®æ¬¡
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®1 â ä»å
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®1.5
- F#ã§ã®ãæ«å°¾ãã«ã¤ãã¦ã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®2
- .NETã«ãããæ«å°¾æé©åã®æ¹æ³ã«ã¤ãã¦ã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®2.5
- ç¶ç¶ã¢ããã¨ãF#ã®æ®å¿µãã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®3
- ãã¹ã¦ãããããã¦å帰ãwhileã«æ¸ãç´ãæ¹æ³ã®è©±
ã¯ããã«
ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ãããã¯ç¶ç¶æ¸¡ãå½¢å¼(Continuation Passing Styleã以éCPS)ã¨ããè¨èãèãããã¨ãããã§ããããã ä»æ¥ã¯CPSã®è©±ããã¾ãã åæç¥èã¯ãF#ã®ã¿ã§ãã
ç¶ç¶ã¨ã¯
CPSã®åã«ãã¾ãã¯ç¶ç¶ã®è©±ã§ãã ç¶ç¶ã¨è¨ã£ã¦ããç¶ç¶çã¤ã³ãã°ã¬ã¼ã·ã§ã³ã¨ãç¶ç¶çããªããªã¨ã¯ã¾ã£ãããããã£ã½ã£ã¡ãé¢ä¿ããã¾ããã®ã§ãããã話é¡ãæå¾ ãã人ã¯åãå³ã ãããã®æèã§ã¯ç¶ç¶ã¯ãç¹°ãè¿ããã¨ããããªé¢¨ãªæå³ãå«ãã§ãã¾ãããä»åæ±ãç¶ç¶ã¯ãç¶ããã¨ããããªæå³ã¨ã¨ããã¦ãã ããã
ç¶ãã£ãã£ã¦ä½ã®ç¶ãã ãã¨ãªãããã§ããããã£ãã説æããã¨ã
ãããã°ã©ã ã®ããç¬éãèããã¨ãã«ããã®ç¬éããå¾ã«å®è¡ãããå¦çã
ãç¶ç¶ã§ãã
ããã°ã©ã ã®ãããã°ã§ãã¬ã¼ã¯ãã¤ã³ããè²¼ã£ã¦å¦çããã¬ã¼ã¯ããã¨ãã«ãããã®ãã¨ã«å®è¡ãããå¦çãã£ã¦ãããããªãã§ããã ãããããã°ã©ãã³ã°ã®å¯¾è±¡ã«ãã¦ãã¾ãããã¨ãããããªè©±ã ã¨æã£ã¦ãã ããã
let x = f 42 (* ããã§ãã¬ã¼ã¯ãã¦ãfããæ»ã£ã¦ããç¶æ (fã¯å®è¡æ¸ã¿) *) printfn "%d" x
ã³ã¡ã³ãã«æ¸ãããããªç¶æ ã ã¨æã£ã¦ãã ããã ãã®ã¨ãã«ãç¶ç¶ã¯
+---------+ | let x = | f 42 | +------+ | printfn "%d" x | +----------------+
ãã®æ ã§å²ãããé¨åã§ãã
=
ã®å·¦å´ãè¨ç®ããã¦ãããã®çµæãå³å´ã®å¤æ°x
ã«è¨å®ãããã®ã§ãlet x =
ã®é¨åãç¶ç¶ã«å«ãã¦ãã¾ãã
ãã¦ããããããã°ã©ãã³ã°ã®å¯¾è±¡ã«ããã«ã¯ã©ãããã°ããã§ãããï¼
ç¶ç¶ãç¡åé¢æ°ã§è¡¨ã
ä¸ã¤ã®æ¹æ³ã¨ãã¦ãããã°ã©ã ãå¤å½¢ãã¦ç¶ç¶ãç¡åé¢æ°ã§è¡¨ããã¨ããã®ãããã¾ãã ãã£ã¦ã¿ã¾ãããã
f 42 |> (fun x -> printfn "%d" x)
ä¸ã®ã³ã¼ãã¨ãã®ã³ã¼ããåãåä½ããããã¨ã¯åããã§ããããã
å
ã»ã©ã¯let
ã®ä¸é¨åãç¶ç¶ã«å«ã¾ãã¦ããã®ã§ãããã°ã©ãã³ã°ã®å¯¾è±¡ã«åºæ¥ãªãããã§ããã
ããã«å¯¾ãã¦ããã®ã³ã¼ãã§ã¯å
ã»ã©ã®ä¾ã¨åãç¶ç¶ã¯
+-----------+ f 42 |> | (fun x -> | +---------+ | | printfn "%d" x) | +---------------------+
ãã®æ ã§å²ãããé¨åã§ã(|>
æ¼ç®åã¯ä½¿ããªããã¨ãã§ããã®ã§å«ãã¦ãã¾ãã)ã
ãããªãããã®é¢æ°èªä½ãããã°ã©ãã³ã°ã®å¯¾è±¡ã«åºæ¥ã¾ããï¼
(* ãã¯ãå¤ã¨ãã¦ã®é¢æ°ã§ãããªã *) let cont = (fun x -> printfn "%d" x)
ããã ãã ã¨ããããã¿ããã£ã±ãã§ãããç¶ç¶ã¯é¢æ°ã¨ãã¦è¡¨ãããã¨ãããã¨ããããã¾ããã
ç¡åé¢æ°ã§letã代ç¨ãã
å
ã»ã©ã®å¤å½¢ã«ãã£ã¦ãlet
ãæ¶ããã®ã«æ°ã¥ããã§ããããï¼
let
ã«ãã£ã¦å°å
¥ãã¦ããå¤æ°ã¯ãç¶ç¶ã表ãç¡åé¢æ°ã®å¼æ°ã«å¤ããã¾ããã
let
ãç¡åé¢æ°ã§è¡¨ããã¨ã¯å¾ã§éè¦ã«ãªã£ã¦ããã®ã§ãããå°ã詳ããè¦ã¦ã¿ã¾ãããã
ãã®ãããªããã°ã©ã ããã£ãã¨ãã¾ãã
let x = f 42 let y = g x let z = h y printfn "%A" (x, y, z)
ãããlet
ã使ããã«ç¡åé¢æ°ã ãã§æ¸ãã¦ã¿ã¾ãã
f 42 |> (fun x -> g x |> (fun y -> h y |> (fun z -> printfn "%A" (x, y, z) )))
f 42
ããå¾ãã表ãç¶ç¶ã¯f 42
ã®æ»ãå¤ãx
ã¨ãã¦å¼æ°ã§åãåãã¾ãã
ããã¦ãg x
ããå¾ãã表ãç¶ç¶ã¯g x
ã®æ»ãå¤ãy
ã¨ãã¦å¼æ°ã§åãåãã¾ãã
h y
ãã以ä¸ç¥ã
ãã®ããã«ãç¶ç¶ãèµ·åãã(ç¶ç¶ã表ãé¢æ°ãå¼ã³åºãã)å´ã®çµæã¯ãå¼æ°ã¨ãã¦åãåãããã®ç¶ç¶ã®ä¸ã§ä½¿ãã¾ãã
ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«(CPS)
fã¨gã¨hããããããã®ãããªé¢æ°ã ã£ãã¨ãã¾ãããã
let f x = x / 2 // int -> int (intãåãåã£ã¦intãè¿ãé¢æ°) let g x = x + 10 // åä¸ let h x = string x // int -> string (intãåãåã£ã¦stringãè¿ãé¢æ°)
ãããå
ã«ãã¦ãåé¢æ°ããèªèº«ã®å¦çãããå¾ã®ç¶ç¶cont
*1ããåãåããããã«ãã¦ã¿ã¾ãã
let fCont x cont = x / 2 |> cont // int -> (int -> 'a) -> 'a (intã¨ãintãåãåã£ã¦ä½ã('a)ãè¿ãé¢æ°ããåãåã£ã¦ä½ã('a)ãè¿ãé¢æ°) // å ã®é¢æ°ã§ã®æ»ãå¤ã¯ã第äºå¼æ°ã§æ¸¡ãããé¢æ°ã®å¼æ°ã«ãªã£ã¦ãã let gCont x cont = x + 10 |> cont // åä¸ let hCont x cont = string x |> cont // int -> (string -> 'a) -> 'a (intã¨ãstringãåãåã£ã¦ä½ã('a)ãè¿ãé¢æ°ããåãåã£ã¦ä½ã('a)ãè¿ãé¢æ°) // å ã®é¢æ°ã§ã®æ»ãå¤ã¯ã第äºå¼æ°ã§æ¸¡ãããé¢æ°ã®å¼æ°ã«ãªã£ã¦ãã
ãã®ããã«ããèªèº«ã®å¦çãããå¾ã®ç¶ç¶ããåãåãé¢æ°ã®ãã¨ãããç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ãã¨è¨ãã¾ãã
å
ã®é¢æ°ã§ã¯çµæã¯ãã®ã¾ã¾å¼ã³åºãå
ã«è¿ãã¦ãã¾ãããããã®ãã¼ã¸ã§ã³ã§ã¯cont
ã«çµæã渡ãã¦ãã¾ãã
cont
ã¯ãèªèº«ãå¦çããå¾ã®ç¶ç¶ãã§ããããããã«çµæã渡ããã¨ã«ãã£ã¦ãcont
ã®ä¸ã§çµæã使ããããã«ããããã§ãã
fCont
ã¯ã©ããã£ã¦ä½¿ãã°ããã§ããããï¼
f
ã§ããã°ãä¾ãã°ãã®ããã«ä½¿ã£ã¦ãã¾ããã
let res = f 10 ...
fCont
ã¯ãã®ããã«ä½¿ãã¾ãã
fCont 10 (fun res -> ...)
ãç¡åé¢æ°ã§let
ã代ç¨ãããã§è¦ããããªæ¸ãæ¹ã«ãªã£ã¦ãã¾ããã
ãç¡åé¢æ°ã§let
ã代ç¨ãããã§ã¯ã|>
æ¼ç®åã使ã£ã¦é çªãå
¥ãæ¿ãã¦ãã¾ããããç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã使ãå ´åã¯ä¸è¦ã§ãã
ãã®ããã«ãç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã使ã£ã¦ç¶ç¶ã渡ãããã°ã©ãã³ã°ã¹ã¿ã¤ã«ãããç¶ç¶æ¸¡ãã¹ã¿ã¤ã«(CPS)ãã§ãã
fCont 42 (fun x -> gCont x (fun y -> hCont y (fun z -> printfn "%A" (x, y, z) )))
ããããã¯ç¶ç¶ãé¢æ°ã¨ãã¦è¡¨ããã¨ä½ãå¬ãããã説æããããã®æºåã¨ãªããã¨ã説æãã¾ãã
æ«å°¾å¼ã³åºã
æ«å°¾å¼ã³åºãã¨ããã®ã¯ãé¢æ°ãå¼ã³åºããå¾ã«çµæãæ»ã以å¤ã«ãããã¨ããªããããªé¢æ°å¼ã³åºãã®ãã¨ãè¨ãã¾ã*2ã ãã¦ãã§ã¯f1, f2, f3ã®ä¸ã§æ«å°¾å¼ã³åºãããã¦ããé¢æ°ã¯ã©ãã§ããããï¼
let example x = if f1 x then f2 x else 10 + f3 x
çãã¯ãf2ã ãã§ãã
f1ãæ«å°¾å¼ã³åºããããªãã¨ããã®ã¯ãf1ãå¼ã³åºããå¾ã«then
ç¯ãelse
ç¯ãå®è¡ããå¿
è¦ããããã¨ããåããã¾ãã
f2ã®å¾ã«else
ãããããã«æããããããã¾ããããthen
ç¯ã¨else
ç¯ã¯äºè
æä¸ã§ãããthen
ç¯ãé¸ã°ããã¨ãã«ã¯else
ç¯ã¯å®è¡ããã¾ããã
then
ç¯ã§ã¯f2ãå¼ã³åºããå¾ã¯ä½ããããã¨ãªããã®çµæãæ»ãã ããªã®ã§ãf2ã¯æ«å°¾å¼ã³åºãã§ãã
f3ã®å¼ã³åºãã¯ããã®çµæã使ã£ã¦10ã¨å ç®ããã¨ããå¦çãf3ããæ»ã£ã¦ããã¨ãã«å¿ è¦ã§ãã ãã®ãããf3ã¯æ«å°¾å¼ã³åºãã§ã¯ããã¾ããã
ä½ããæ«å°¾ãã«ãªãã®ãã¯ä»åã¯æ¨ªéãªã®ã§æ·±å ¥ãã¯ãã¾ããããå¥ã®æ©ä¼ã«(F#ã«ã¤ãã¦ã¯)ã¾ã¨ãããã¨æãã¾ãã
æ«å°¾å¼ã³åºãã®æé©å
æ«å°¾å¼ã³åºãã¯ãé¢æ°ããæ»ã£ã¦ããå¾ã«çµæãæ»ã以å¤ã«ãããã¨ããªããããªé¢æ°å¼ã³åºããã§ããã ä½ããããã¨ããªãã®ãªããé¢æ°å¼ã³åºããããªãã¦ãåãªãã¸ã£ã³ãå½ä»¤ã«ç½®ãæãã¦ãã¾ãã°ã¹ã¿ãã¯ãæ¶è²»ããªããªã£ã¦ããããï¼ ã¨ããã®ãæ«å°¾å¼ã³åºãã®æé©åã§ã*3ã
ãããå¬ããã®ã¯ãä¾ãã°å帰é¢æ°ãæ«å°¾å¼ã³åºãã«ãªã£ã¦ããå ´åã§ã*4ã ãã®ãããªå帰ãæ«å°¾å帰ã¨è¨ã£ãããã¾ãã æ«å°¾å¼ã³åºããæé©åãããªãã¨ãå帰ã®åæ°ãç©ã¿éãªãã¨ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãèµ·ããã¦ãã¾ãã¾ãã æ«å°¾å¼ã³åºããæé©åããããã¨ã§ãå帰ã®åæ°ãç©ã¿éãªã£ã¦ãã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãèµ·ãããªããªããããå帰ã®åæ°ãå¤ããªãå¾ãé¢æ°ã¯æ«å°¾å¼ã³åºãã®æé©åããããããã«æ«å°¾å帰ã®å½¢ã«å¤å½¢ãããã¨ãããã¾ãã å¼æ¨ã®å¤å½¢ãªã©ãåç´ã«æ¸ãã¨æ«å°¾å帰ã«ãªããªãå帰ã¯å±±ã®ããã«ããã®ã§ãæ«å°¾å帰ã®å½¢ã«å¤å½¢ããæ¹æ³ã¯éè¦ã§ãã
ããä¸å¿è¨ã£ã¦ããã¨ãæ«å°¾å¼ã³åºãã®æé©åãããããã©ããã¯è¨èªãå¦çç³»ã«ãã£ã¦éãã¾ãã®ã§ã æ«å°¾å帰ã«å¤å½¢ããããã¨è¨ã£ã¦ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãèµ·ããªããªããã¨ãä¿è¨¼ãããããã§ã¯ããã¾ããã èªåã®å¥½ããªãã®è¨èªããã®å¦çç³»ãæ«å°¾å¼ã³åºãã®æé©åãããããã©ãã調ã¹ã¦ããã¨ããã§ãããã
CPSå¤æã«ããæ«å°¾å帰é¢æ°ã¸ã®å¤æ
ãã¦ã話ãç¶ç¶ã«æ»ãã¾ãã CPSã«å¤å½¢(CPSå¤æ)ãããã¨ã§ãèªåçã«æ«å°¾å帰ã®é¢æ°ãæã«å ¥ãã®ã§ãï¼ ãªããããªãã®ããè¦ã¦ã¿ã¾ãããã
ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã¨ãããã使ãããã°ã©ã ã§ãã
let fCont x cont = x / 2 |> cont let gCont x cont = x + 10 |> cont let hCont x cont = string x |> cont let program () = fCont 42 (fun x -> gCont x (fun y -> hCont y (fun z -> printfn "%A" (x, y, z) )))
ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã¯ãç¶ç¶ãæ«å°¾å¼ã³åºããã¦ããã®ãä¸ç®ã§åããã¾ãã ã§ã¯ãç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã使ã£ã¦ããå´ã¯ã©ãã§ããããã ãã¡ãããããããã®é¢æ°ã¯æ«å°¾å¼ã³åºãã«ãªã£ã¦ãã¾ãã ã¤ã³ãã³ãã追å ããã¨ããããããã§ãããã
let program () = // fContã®å¼ã³åºãã¯ãprogramé¢æ°ã®æ«å°¾ã§è¡ããã¦ãã // gContãªã©ã®å¼ã³åºãã¯ãé¢æ°ã§ããã¾ããä¸ã«ãããã®å ´ã§ã¯å¼ã³åºãããªã fCont 42 (fun x -> // gContã®å¼ã³åºãã¯ãfContã®ç¶ç¶ã®æ«å°¾ã§è¡ããã¦ãã // hContãªã©ã®å¼ã³åºãã¯ãé¢æ°ã§ããã¾ããä¸ã«ããã®ã§ãã®å ´ã§ã¯å¼ã³åºãããªã gCont x (fun y -> // hContã®å¼ã³åºãã¯ãgContã®ç¶ç¶ã®æ«å°¾ã§è¡ããã¦ãã hCont y (fun z -> printfn "%A" (x, y, z) ) ) )
ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ã§ã¯ãé¢æ°ã®æå¾ã¯ãç¶ç¶ã表ãé¢æ°ã«çµæã渡ãããã¨ã«ãªãã¾ãã*5ã ç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã®é¢æ°ãå¼ã³åºãå ´åããã¯ãæ«å°¾å¼ã³åºãã«ãªãã¾ãã ãã®ãããå帰é¨åãç¶ç¶æ¸¡ãã¹ã¿ã¤ã«ã§æ¸ãã°èªåçã«æ«å°¾å¼ã³åºãã«ãªãã®ã§ãã
ã¤ã¾ããæ«å°¾å帰ã§ã¯ãªãå帰é¢æ°ãCPSå¤æãããæ«å°¾å帰é¢æ°ã«ãªããæ«å°¾å¼ã³åºãã®æé©åããããã¾ãã ãããããCPSå¤æã®ãããããåããã¨ããã¾ã§æ¥ã¾ããã ã§ã¯ãæ«å°¾å¼ã³åºãã«ãªã£ã¦ããªãå帰é¢æ°ãCPSå¤æãã¦ã¿ã¾ãããã
éä¹ãCPSå¤æ
ç°¡åãªä¾ã¨ãã¦ãéä¹ãããã£ã¦ã¿ã¾ãã ã¾ãã¯ãæ«å°¾å帰ã§ã¯ãªãfactã®å®ç¾©ã§ãã
let rec fact = function | n when n = 0I -> 1I | n -> n * (fact (n - 1I))
bigint
ãå®æ°ãã¿ã¼ã³ã¨ãã¦ä½¿ããªãã®ã§when
ã使ã£ã¦ããã®ãã¡ãã£ã¨æ®å¿µã§ããããã以å¤ã¯æ®éã®ã³ã¼ãã§ãã
ãã®é¢æ°ã¯ãå帰å¼ã³åºããããå¾ã«ãã®çµæã¨n
ã®å¤ãæãã¦ãããããæ«å°¾å帰ã«ãªã£ã¦ãã¾ããã
ãã®ããããã®é¢æ°ã«50000I
ã渡ãã¨ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãèµ·ãã¾ããã
ããããã¾ãã¯å帰å¼ã³åºãé¨åãlet
ã使ã£ãå½¢ã«æ¸ãæãã¾ãã
let
ã使ã£ãå½¢ã«ããã¨CPSå¤æãããããªãã®ã§ãæ
£ããªããã¡ã¯ã¾ãã¯let
ã使ã£ãå½¢ã«å¤å½¢ããã¨ããããå§ããã¨ããã§ãããã
let rec fact n = if n = 0I then 1I else let pre = fact (n - 1I) n * pre
次ã«ããããCPSã«æ¸ãæãã¾ãã
ã¾ãã¯ãç¶ç¶ãå¼æ°cont
ã¨ãã¦åãåãããã«ãã¾ãã
(* å¤æéä¸ *) let rec fact' n cont = if n = 0I then 1I else let pre = fact' (n - 1I) n * pre
cont
ã¯ç¶ç¶ãªã®ã§ãfact'
ã®å¦çã®çµæã渡ãã¦ããããã¨ã§fact'
ã®å¾ãã®å¦çãå®è¡ãã¾ãã
ããã§ããããï¼
(* å¤æéä¸: elseããããã *) let rec fact' n cont = if n = 0I then 1I |> cont else let pre = fact' (n - 1I) n * pre |> cont
ããã¯ã³ã³ãã¤ã«ãéãã¾ããã
fact'
ã¯ç¬¬äºå¼æ°ã¨ãã¦ç¶ç¶ãåãåããããpre
ã¯fact'
ã®çµæã§ã¯ãªãé¢æ°ã«ãªã£ã¦ãã¾ã£ã¦ãã¾ãã
ããã§ãfact'
ãå¼ã³åºããå¾ã®å¦ç(n * pre |> cont
)ãfact'
ã«æ¸¡ãç¡åé¢æ°ã®ä¸ã«å
¥ãã¦ãã¾ãã¾ãã
(* å¤æå®äºï¼ *) let rec fact' n cont = if n = 0I then 1I |> cont else fact' (n - 1I) (fun pre -> n * pre |> cont)
let
ã§å°å
¥ãããå¤æ°ãç¡åé¢æ°ã®å¼æ°ã¨ãã¦å°å
¥ããå½¢ã«ããã®ã¯ãä»ã¾ã§ä½åãè¦ã¦ãã¦ããã®ã§å¤§ä¸å¤«ã§ãããã
ããã§ç¡äºãCPSå¤æã§ãã¾ããï¼
ããããã®ã¾ã¾ã§ã¯å
ã®é¢æ°ã¨åã使ãæ¹ãã§ãã¾ããã
ãã¹ã¿ãã¯ãªã¼ãã¼ããã¼ããªããªãã¾ãããã代åã¨ãã¦ç¶ç¶ã渡ãå¿
è¦ãã§ãã¾ããï¼ãã§ã¯é§ç®ã§ãããã
ããã§ãCPSãªé¢æ°ãã©ããããé¢æ°ãç¨æãã¾ãã
CPSçã®fact'ãã©ãããã
ãã¦ãfact'
ãå¤ããå¼ã³åºãå ´åãcont
ã«ã¯ä½ã渡ãã°ããã§ããããï¼
ãããèããåã«ãfact'
ã®ã·ã°ããã£ã確èªãã¦ã¿ã¾ãããã
val fact' : n:System.Numerics.BigInteger -> cont:(System.Numerics.BigInteger -> 'a) -> 'a
System.Numerics.BigIntger
ã®å¥åã¨ãã¦bigint
ãããã®ã§ãããã使ã£ã¦æ¸ãç´ãã¨ã
val fact' : n:bigint -> cont:(bigint -> 'a) -> 'a
ããã§ãã ããããåããã®ã¯ã
- ç¶ç¶ã表ãé¢æ°
cont
ã«ã¯ãfact'
ãè¨ç®ããçµæã渡ããã - ç¶ç¶ã表ãé¢æ°
cont
ã¯ãä»»æã®çµæåãè¿ãã - ç¶ç¶ã表ãé¢æ°
cont
ãè¿ããåããfact'
å ¨ä½ã®çµæåã«ãªã
ã§ãã
1ã¤ç®ã¯ãä»ã¾ã§è¦ã¦ããéãã®ãã¨ã§ããç¶ç¶ã«ã¯çµæã渡ããã¾ãã
2ã¤ç®ã¨3ã¤ç®ã«æ³¨ç®ãã¦ãã ããã
ä»ã¾ã§ãä¸çªå¤å´(ä¸çªæ·±ãé¨å)ã®ç¶ç¶ã§ã¯ãprintfn
ã«ããåºåãè¡ã£ã¦ãã¾ããã
fact' 5 (fun res -> printfn "%d" res)
ä»ã¾ã§éããªããããªæãã§ãã ãããä¸ã®3ã¤ã«å½ã¦ã¯ãã¦ã¿ãã¨ã
res
ã«ã¯fact'
ãè¨ç®ããçµæãå ¥ã£ã¦ããprintfn "%d" res
ã¯fact'
ãè¨ç®ããçµæãåºåãã¦ãunit
ãè¿ãfact'
ã«æ¸¡ããç¶ç¶ãunit
ãè¿ãã®ã§ãfact'
ã®å¼ã³åºãå ¨ä½ã¨ãã¦ãunit
ãè¿ã
ã¨ãªãã¾ãã
ã¨ãããã¨ã¯ãCPSå¤æãããé¢æ°ããå¤ãåãåºãã«ã¯ãç¶ç¶ã«æ¸¡ãããçµæããã®ã¾ã¾è¿ãã°ããã¨ãããã¨ã«ãªãã¾ãã
ããã¯ãç¶ç¶ã¨ãã¦id
é¢æ°ã渡ãã°ãããã¨ãããã¨ã§ããã
let res = fact' 5 id printfn "%d" res
ã¤ã¾ããããé¢æ°åããã°ãfact
ã®ã¦ã¼ã¶ã¯ä¸ã§CPSå¤æãããé¢æ°ã«å®è£
ãå¤ãã£ã¦ããªã«ãæ°ã«ããªãã¦ããããã§ãã
let fact n = fact' n id
fact'
ãå¤ãã使ãããªãããã«ããããã«ãé¢æ°å
é¢æ°ã«ãã¦ãããã§ãããã
let fact n = let rec fact' n cont = if n = 0I then 1I |> cont else fact' (n - 1I) (fun pre -> n * pre |> cont) fact' n id
ããã§å¤æå®äºã§ãã
å®éã«ããã試ããã人ã¯ãããã¸ã§ã¯ãã®ããããã£ãããæ«å°¾å¼ã³åºãã®çæãããªã³ã«ãã¦ãã ãã(Releaseã¢ã¼ãã§ããã°ããã©ã«ãã§ãªã³ã®ã¯ãã§ã)ã
ã¾ããfsi
ã§ããã°è¨å®ä¸è¦ã§è©¦ãã¾ãã
ãã®é¢æ°ã«ã¯ã50000I
ã渡ãã¦ãã¹ã¿ãã¯ãªã¼ãã¼ããã¼ã¯èµ·ããã¾ããã
CPSå¤æããããã¨ã«ãã£ã¦ãæ«å°¾å帰ã«ãªããæ«å°¾å¼ã³åºãã®æé©åãããã£ãããã§ãã
ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãããããªå帰ãæ¸ãã¦ãã¾ã£ãã¨ãã«ãCPSå¤æãè¡ãã°ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåé¿ã§ããããã«ãªãã¾ãã ä»ã«ãåé¿ããæ¹æ³ã¯ããã¾ã*6ãã CPSå¤æã¯æ £ãã¦ãã¾ãã°ã»ã¨ãã©æ©æ¢°çã«è¡ããã®ã§ãèªåã®éå ·ç®±ã«å ¥ãã¦ããã¦ãããã§ãããã
ãã®2ã¯ã³ã³ãã¥ãã¼ã·ã§ã³å¼ã®è©±ã«ãªãäºå®ã§ãã
ãã¾ã
ããããã¯ãã¾ãã§ãããããã¯ãã¼ãã¹ã¹ãã¼ã¸ã è²ã ãªé¢æ°ãCPSå¤æãã¦ã¿ã¾ãããã
sumé¢æ°
ãªãªã¸ãã«
let rec sum = function | [] -> 0 | x::xs -> x + (sum xs)
letã§æ¸ãæã
let rec sum xs = match xs with | [] -> 0 | x::xs -> let pre = sum xs x + pre
CPS!
let rec sum xs cont = match xs with | [] -> 0 |> cont | x::xs -> sum xs (fun pre -> x + pre |> cont)
ããid
渡ãã©ããã¼é¢æ°ã¯èªæãªã®ã§æ¸ãã¾ããã
maxé¢æ°ãCPSå¤æ
ãªãªã¸ãã«
let rec max = function | [x] -> x | x::xs -> let pre = max xs if pre < x then x else pre
letã§æ¸ãæã
let
ã§æ¸ãæãèªä½ã¯ä¸è¦ã ãã©ãfunction
ãmatch
ã«ãã¦ããã
let rec max xs = match xs with | [x] -> x | x::xs -> let pre = max xs if pre < x then x else pre
CPS!
let rec max xs cont = match xs with | [x] -> x |> cont | x::xs -> max xs (fun pre -> if pre < x then x |> cont else pre |> cont)
findé¢æ°ãCPSå¤æ
ãªãªã¸ãã«
let rec find pred = function | [] -> failwith "not found." | x::xs -> if pred x then x else find pred xs
letã§æ¸ãæã
let rec find pred xs = match xs with | [] -> failwith "not found." | x::xs -> if pred x then x else let res = find pred xs res
CPS!
let rec find pred xs cont = match xs with | [] -> failwith "not found." | x::xs -> if pred x then x |> cont else find pred xs cont (* (fun res -> res |> cont)ãªã®ã§ãåã«contã渡ãã°ãã *)
mapé¢æ°ãCPSå¤æ
ãªãªã¸ãã«
let rec map f = function | [] -> [] | x::xs -> (f x) :: (map f xs)
letã§æ¸ãæã
let rec map f xs = match xs with | [] -> [] | x::xs -> let y = f x let ys = map f xs y::ys
CPS!
let rec map f xs cont = match xs with | [] -> [] |> cont | x::xs -> let y = f x map f xs (fun ys -> y::ys |> cont)
ããã¯ãmap
èªä½ã®CPSå¤æã§ãã
f
ãCPSå¤æãããé¢æ°ã®å ´åã¯ã
let rec map f xs cont = match xs with | [] -> [] |> cont | x::xs -> f x (fun y -> map f xs (fun ys -> y::ys |> cont))
ããã§ããã
ãã£ããããé¢æ°ãCPSå¤æ
ãªãªã¸ãã«
let rec fib = function | 0 | 1 -> 1 | n -> fib (n - 1) + fib (n - 2)
letã§æ¸ãæã
let rec fib n = match n with | 0 | 1 -> 1 | n -> let pre1 = fib (n - 1) let pre2 = fib (n - 2) pre1 + pre2
CPS!
let rec fib n cont = match n with | 0 | 1 -> 1 |> cont | n -> fib (n - 1) (fun pre1 -> fib (n - 2) (fun pre2 -> pre1 + pre2 |> cont))
*1:contã¯continuationã®ç¥ã§ããç¶ç¶ã表ãå¤æ°åã«ã¯ä»ã«ãkãªã©ã使ãããããã¾ãã
*2:å帰é¢æ°ã®ãã¨ãæ±ãå ´åãå¤ãã§ãããå帰é¢æ°ã§ãªãã¨ãæ«å°¾å¼ã³åºãã¨è¨ãã¾ãã
*3:èªåèªèº«ã®ã¹ã¿ãã¯ãåå©ç¨ããããã«ã¼ãã«å¤å½¢ãããã¨ããããæ¹ãããã¾ãããã©ã®æ¹æ³ã§ãã¹ã¿ãã¯ãæ¶è²»ããªãã¨ããå¹æã¯åãã§ãã
*4:ä»ã«ããChain of Responsibilityãã¿ã¼ã³ãé©ç¨ããéã«å¤§éã®ãªãã¸ã§ã¯ããchainãæ§æããå ´åãªã©ãå帰ããªãå ´åã§ãããããå ´é¢ã¯ããã¾ãã
*5:ä¾å¤ãæããã¨ããç¶ç¶ãæ¨ã¦ãã¨ãã¯ç¡è¦ãã¾ãã
*6:ã¢ãã¥ã ã¬ã¼ã¿å¤æ°ã使ãæ¹æ³ããã«ã¼ãã«æ¸ãæããæ¹æ³ãªã©ã使ãã¾ãã