å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®3
é£è¼ç®æ¬¡
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®1
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®1.5
- F#ã§ã®ãæ«å°¾ãã«ã¤ãã¦ã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®2
- .NETã«ãããæ«å°¾æé©åã®æ¹æ³ã«ã¤ãã¦ã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®2.5
- ç¶ç¶ã¢ããã¨ãF#ã®æ®å¿µãã®è©±
- å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®3 â ä»å
- ãã¹ã¦ãããããã¦å帰ãwhileã«æ¸ãç´ãæ¹æ³ã®è©±
ã¯ããã«
å帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåã話 ãã®2ã®ç¶ãã§ãæå¾ã§ãã ååã¯CPSå¤æããã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåé¿ã§ããªãå ´åããããã¨ãã話ã§ããã åæç¥èã¯ãF#ã¨ãã¹ã¿ãã¯ã«ã¤ãã¦ã§ãã ããã¾ã§ã¯CPSã®è©±ãä¸å¿ã«ãã¦ãã¾ãããããã®è¨äºã§ã¯CPSã®ç¥èã¨ãä¸è¦ã§ãã
F#ã§å帰é¢æ°ã«ãã£ã¦ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãèµ·ããå ´åã«ããããåé¿ããæ¹æ³ã¨ãã¦ã¯ãã®1ã§è¦ãããã«ãCPSå¤æããã¨ããã®ãããã¾ãã ãããããã®æ¹æ³ã¯ãã®2ã§è¦ãããã«å®å ¨ã§ã¯ããã¾ããã
ãã®ã»ãã®æ¹æ³ã¨ãã¦ã¯ãCPSã§ã¯ãªãå½¢ã§æ«å°¾å帰ã«ããæ¹æ³ãèãããã¾ãã
CPSã§ãªãå½¢ã§æ«å°¾å帰ã«ããã°ãtail.
ILãã¬ãã£ãã¯ã¹ã«ããæ¹æ³ã§ã¯ãªããã«ã¼ãã«å¤æããããã¨ã«ããæé©åãå¹ãããã«ãªãã®ã§ãã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãé²ãã¾ãã
ããããCPSå¤æã¯ã»ã¨ãã©æ©æ¢°çã«æ«å°¾å帰ã«æ¸ãæãå¯è½ã§ããããCPSå¤æã使ããã«æ«å°¾å帰ã«æ¸ãæããã®ã¯å¸¸äººã«ã¯ã¤ãããã®ãããã¾ãã
ã©ããããããªãã®ã§ãæå¾ã®æ段ã§ãã ã³ã³ãã¤ã©ã¯åç´ãªå帰ããã«ã¼ãã«å¤æãã¦ããã¾ãããã人éãªãã»ã»ã»äººéãªãå帰ãã«ã¼ãã«å¤æã§ããã®ã§ã¯ï¼
ã¨ãããã¨ã§ãå帰é¢æ°ã®ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãåãããã«ãå帰é¢æ°ãã«ã¼ãã§æ¸ãç´ãã¦ãã¾ãã¾ãããï¼ ã¤ãã¥ã¼ã¿ãã«ï¼é¢æ°åè¨èªï¼ãªã«ããããããã®ï¼ï¼ï¼
å帰ãwhileã§æ¸ãæãã
ã§ã¯ãã©ããã£ã¦å帰ãwhile
ã§æ¸ãæããã°ããã®ã§ããããï¼
ç°¡åãªä¾ããè¦ã¦ããã¾ãããã
æ«å°¾å帰é¢æ°ãwhileã§æ¸ãæãã
æ«å°¾å帰é¢æ°ã¯ç°¡åã«while
ã«æ¸ãæãå¯è½ã§ãã
let fact n = let rec fact' acc = function | 0 -> acc | n -> fact (acc * n) (n - 1) fact' 1 n
ã¢ãã¥ã ã¬ã¼ã¿å¤æ°ã使ã£ãéä¹ã®è¨ç®ãããé¢æ°ã§ãã
ãããwhile
ã§æ¸ãæããã¨ä¾ãã°ãããªãã¾ãã
let fact n = let mutable n = n (* æ¸ãæãå¯è½å¤æ°ã§å¼æ°ãã·ã£ãã¼ã¤ã³ã° *) let mutable acc = 1 (* fact' 1 nã«ç¸å½ãaccã®åæå¤ãè¨å® *) while n <> 0 do (* ã«ã¼ãå¤å®ã«ã¯ãå ã®å帰é¢æ°ã®çµäºæ¡ä»¶ã®å¦å®ãæ¸ã *) acc <- acc * n (* fact (acc * n) (n - 1)ã®ãã¡ãè¨ç®ã®ä¸»ä½ãaccã«åä»£å ¥ *) n <- n - 1 (* fact (acc * n) (n - 1)ã®ãã¡ãçµäºæ¡ä»¶ã«é¢ããé¨åãnã«åä»£å ¥ *) acc (* ã«ã¼ããæããéã«accã«çµæãå ¥ã£ã¦ãã *)
æé ã¯å¤§ä½ä»¥ä¸ã®éãã§ãã
- çµäºæ¡ä»¶å¤å®ã®ããã®å¤æ°ã
mutable
ã§ä½ã - çµææ ¼ç´ç¨ã®å¤æ°ã
mutable
ã§ä½ããåæå¤ãå ¥ãã¦ãã - å帰é¢æ°ã®çµäºæ¡ä»¶ã®å¦å®ã
while
ã®ã«ã¼ãå¤å®ã«ãã- ã«ã¼ããç¶è¡ããæ¡ä»¶ãªã®ã§ãçµäºæ¡ä»¶ã®å¦å®ã«ãªã
- è¤æ°ã®çµäºæ¡ä»¶ãããå ´åã¯ã
&&
ã§ã¤ãªã(ä¸ã¤ã§ãå帰ã®çµäºæ¡ä»¶ãæºããã°è±åº â ä¸ã¤ã§ãã«ã¼ãã®ç¶è¡æ¡ä»¶ãç ´ãã°è±åº)
while
ã®ä¸ã«ã¯å帰é¨åãæ¸ã- å帰ã§è¨ç®ãã¦ããé¨åãã³ãã¼ãã¦ãçµææ ¼ç´ç¨ã®å¤æ°ã«çµæãåä»£å ¥
- çµäºæ¡ä»¶å¤å®ã®æ´æ°ããã¦ããé¨åãã³ãã¼ãã¦ãçµäºæ¡ä»¶å¤å®ã®ããã®å¤æ°ã«çµæãåä»£å ¥
ãã®ããã«ç¡äºæ¸ãæãããã¾ããããF#ã§ã¯ãã®ãããªæ«å°¾å帰é¢æ°ãããããã«ã¼ãã«æ¸ãæããå¿ è¦æ§ã¯ãªãã§ãã ã ã£ã¦ãã®ç¨åº¦ãªãã³ã³ãã¤ã©ããã£ã¦ããã¾ããããã
å¼ã³åºãã¹ã¿ãã¯ãå¿ è¦ãªå帰ãwhileã§æ¸ãæãã
æ«å°¾å帰ã§ã¯ãªãå帰ã¯ãç°¡åã«ã¯ã«ã¼ãã«å¤æã§ãã¾ããã ãªããªããå帰å¼ã³åºãããæ»ã£ã¦ããå¾ã«ä½ããã®è¨ç®ãå¿ è¦ãªããã ã©ããã«ãããè¨ç®ããããã®æ å ±ãåã£ã¦ãããªãã¨ãããªãããã§ãã
ä¾ãã°ãæ«å°¾å帰ã§ã¯ãªãéä¹ãè¨ç®ããé¢æ°ãèãã¦ã¿ã¾ãã
let rec fact n = match n with | 0 -> 1 | _ -> n * fact (n - 1)
ãã®é¢æ°ã¯n
ã0
ã§ã¯ãªãã¨ãã«å帰å¾ã«è¨ç®ãå¿
è¦ãªã®ã§ãæ«å°¾å帰çã®æé ã§ã¯while
ã«æ¸ãæãä¸å¯è½ã§ãã
ãã®ç¨®ã®é¢æ°ãwhile
ã§æ¸ãæããã«ã¯ã©ããããããã§ããããï¼*1
ã¾ãã¯ãæ«å°¾å¼ã³åºãã§ã¯ãªãå帰é¢æ°ãã©ã®ããã«ãã¦å®ç¾ããã¦ããããè¦ã¦ã¿ã¾ãããã
æ«å°¾å¼ã³åºãã§ã¯ãªãå帰é¢æ°ã«ã¤ãã¦
æ«å°¾å¼ã³åºãã§ã¯ãªãå帰é¢æ°ã¯ãå¼ã³åºãå ã®æ å ±(ç°å¢)ãå¼ã³åºãã¹ã¿ãã¯ã¨ãã¦ä¿æãããã¨ã§ã å帰å¼ã³åºãããæ»ã£ã¦ããå¾ã§ããã®å¾ã®å¦çãå®è¡ã§ããããã«ãã¦ãã¾ãã
let rec fact n = match n with | 0 -> 1 | _ -> n * fact (n - 1)
ãã®å ´åãfact 2
ãå¼ã³åºãã¨ãã¾ãå¼ã³åºãã¹ã¿ãã¯ã«1ã¤ç°å¢ãç©ã¾ãã¾ãã
+----------------+ | fact { n = 2 } | +----------------+
n
ã0
ã§ã¯ãªãã®ã§n * fact (n - 1)
ã®ãã©ã³ããå®è¡ããã¾ãã
ããã§fact
ãå帰çã«å¼ã³åºãã¦ãã¾ããããã®å¼ã³åºããçµãã£ãå¾ã«ãã®çµæã¨ãã®ç°å¢ã§ã®n
ãä¹ç®ããå¿
è¦ãããã¾ããã
ãã®æ
å ±ãå¼ã³åºãã¹ã¿ãã¯ã«ç©ãã§ãããã¨ã§ãããå¯è½ã«ãã¦ãã¾ãã
fact
å¼ã³åºãããããããã¹ã¿ãã¯ã«æ°ããç°å¢ãç©ã¾ãã¾ãã
+----------------+ | fact { n = 1 } | +----------------+ | fact { n = 2 } | +----------------+
ã¾ãããn * fact (n - 1)
ã®ãã©ã³ããå®è¡ãããã®ã§ãå¼ã³åºãã¹ã¿ãã¯ã«æ°ããç°å¢ãç©ã¾ãã¾ãã
+----------------+ | fact { n = 0 } | +----------------+ | fact { n = 1 } | +----------------+ | fact { n = 2 } | +----------------+
n
ã0
ã®å ´åã1
ã®ãã©ã³ããå®è¡ããã¾ãã
ãã¡ãã®ãã©ã³ãã§ã¯å帰å¼ã³åºãã¯ãã¦ããªãã®ã§ãæ°ããªç°å¢ãå¼ã³åºãã¹ã¿ãã¯ã«ç©ã¾ãããã¨ã¯ããã¾ããã
éã«ãé¢æ°å¼ã³åºããå®äºããããå¼ã³åºãã¹ã¿ãã¯ãæ¶è²»ããã¾ãã
+----------------+ | fact { n = 1 } | +----------------+ | fact { n = 2 } | +----------------+
ãã®ç¶æ
ã§fact 0
ã®å¼ã³åºãå
ã ã£ãn * (fact 0)
ãå®è¡ããã¾ãã
n
ã¯å¼ã³åºãã¹ã¿ãã¯ã«ç©ã¾ããå
é ã®ç°å¢ãåç
§ããã¨1
ã¨åããã®ã§ãfact 0
ã®çµæã¨ä¹ç®ããçµæã¯1
ã«ãªãã¾ãã
ä¹ç®å¾ã«å¿
è¦ãªè¨ç®ã¯ãªããããå¼ã³åºãã¹ã¿ãã¯ãæ¶è²»ããã¾ãã
+----------------+ | fact { n = 2 } | +----------------+
åæ§ã«ã2 * 1
ãå®è¡ãããçµæã¯2
ã«ãªãã¾ãã
æçµçã«fact 2
ã®çµæã¨ãã¦2
ãå¾ããã¾ããã
ãã®ããã«ãå帰é¢æ°ã¯å¼ã³åºãã¹ã¿ãã¯ã使ã£ã¦å®ç¾ããã¦ãã¾ã*2ã ãã®å¼ã³åºãã¹ã¿ãã¯ã«ã¯ãµã¤ãºã®ä¸éãããããããè¶ ãã¦ãã¾ã£ãéã«çºçããã®ãã¹ã¿ãã¯ãªã¼ãã¼ããã¼ã¨ã©ã¼ã§ãã
å¼ã³åºãã¹ã¿ãã¯ãããã°ã©ãã管çãã
ä¸ã§è¦ãå¼ã³åºãã¹ã¿ãã¯ã¯ãå®è¡ç°å¢ãç¨æãã¦ãããã¹ã¿ãã¯ã®ãããã¦ã¼ã¶ããã¯æ±ãã¾ããã
ãããããã°ã©ãã管çãããã¨ã§ãå帰å¼ã³åºãã¨åãåä½ãwhile
ã¨ãã¦åç¾ã§ãã¾ãã
let fact n = (* èªåã§å¼ã³åºãã¹ã¿ãã¯ç¸å½ã®ãã®ãç¨æ *) let stack = System.Collections.Generic.Stack<int>() let mutable n = n (* å¦çãã¹ããã¼ã¿ããã¹ã¦ã¹ã¿ãã¯ã«ç©ã *) while n <> 0 do stack.Push(n) n <- n - 1 let mutable res = 1 // åæå¤ (* ã¹ã¿ãã¯ããªããªãã¾ã§å¦çãã *) while stack.Count <> 0 do res <- res * stack.Pop() // å¦çæ¬ä½ res
ãã®æ¸ãæãã®æ¦ç¥ã§ã¯ãå¦çãã¹ããã¼ã¿ãã¹ã¿ãã¯ã«ç©ããã§ã¼ãºã¨ã ã¹ã¿ãã¯ãããã¼ã¿ãåã£ã¦ãã£ã¦å®éã«å¦çãããã§ã¼ãºã«åãã¦ãã¾ãã ãã®æ¦ç¥ã¯å¦çãã¹ããã¼ã¿ã®ç·éãç°¡åã«ãããå ´åã®ã¿ã«ä½¿ããæ¹æ³ã§ãã
æåã«å¦çãã¹ããã¼ã¿ã®ç·éã¯åãããªããã¨ãå¤ãã®ã§ã ã¹ã¿ãã¯ãããã¼ã¿ãåã£ã¦ã¯ã¹ã¿ãã¯ã«ç©ãå¿ è¦ããããã©ããã確èªãã¦ããã ã¨ããæ¦ç¥ãåããã¨ãå¤ããªãã§ãããã
let fact n = (* èªåã§å¼ã³åºãã¹ã¿ãã¯ç¸å½ã®ãã®ãç¨æ *) let stack = System.Collections.Generic.Stack<int>() stack.Push(n) let mutable res = 1 // åæå¤ (* ã¹ã¿ãã¯ã空ã«ãªãã¾ã§ã«ã¼ããã *) while stack.Count <> 0 do (* Popããçµæã«ãã£ã¦å¦çãåå² *) match stack.Pop() with | 0 -> () (* ã¹ã¿ãã¯ã«ç©ã¾ããå¤ã0ãªããã以ä¸å¦çã¯ããªã *) | nonZero -> (* ã¹ã¿ãã¯ã«ç©ã¾ããå¤ã0以å¤ãªãããã®å¤-1ãã¹ã¿ãã¯ã«ç©ã¿ã çµæãæ´æ° *) stack.Push(nonZero - 1) res <- res * nonZero // å¦çæ¬ä½ res
ãã®æ¦ç¥ã§ã¯ãã«ã¼ãä¸ã§åå²ã«ãã£ã¦æ°ããå¤ãã¹ã¿ãã¯ã«pushãããããªãããåããã¦ãã¾ãã
ãã®ããã«ãã¹ã¿ãã¯ã«ç©ã¾ãã¦ããå¤ã«ãã£ã¦ã¯æ°ããå¥ã®å¤ãã¹ã¿ãã¯ã«ç©ãã¨ããæ¦ç¥ãã¨ãã¨ã
ããã¦ãã®å帰ã¯while
ã«å¤æã§ãã¾ãã
ç¸äºå帰ãwhileã§æ¸ãæãã
å¼æ¨ã®å¤æãªã©ã¯ãç¸äºå帰ã«ãã£ã¦å®ç¾ããã¦ããå ´åãããã¾ãã
ç¸äºå帰ãç´æ¥while
ã«å¤æããã®ã¯é£ããã®ã§ãã¾ãã¯ç¸äºå帰ãèªå·±å帰ã«æ¸ãæãã¦ããã®ãããã§ãããã
let isEven n = let rec isEven' n = match n with | 0 -> true | nonZero -> isOdd (nonZero - 1) and isOdd n = match n with | 0 -> false | nonZero -> isEven' (nonZero - 1) isEven' n
ç¸äºå帰ã®èªå·±å帰ã¸ã®æ¸ãæãã«ã¯ãé¢æ°ã表ãå¤å¥å ±ç¨ä½ãå°å ¥ãã¾ãã
type RecFunc = | CallIsEven of int | CallIsOdd of int let isEven n = let rec loop = function | CallIsEven n -> match n with | 0 -> true (* isEven'ã0ã§å¼ã³åºããå ´åã«ç¸å½ *) | nonZero -> loop (CallIsOdd (nonZero - 1)) (* isEven'ã0以å¤ã§å¼ã³åºããå ´åã«ç¸å½ *) | CallIsOdd n -> match n with | 0 -> false (* isOddã0ã§å¼ã³åºããå ´åã«ç¸å½ *) | nonZero -> loop (CallIsEven (nonZero - 1)) (* isOddã0以å¤ã§å¼ã³åºããå ´åã«ç¸å½ *) loop (CallIsEven n) (* æåã¯isEven'ãå¼ã³åºãã¦ããã®ã§ãCallIsEvenã渡ã *)
ãã¨ã¯ããã®é¢æ°ãããã¾ã§ã®ç¥èãå
ã«ãã¦while
ã«æ¸ãæãã¾ãã
ä»åã¯åç´ãªä¾ãªã®ã§ãã¹ã¿ãã¯ãèªåã§ç®¡çããã«æ¸ãæãå¯è½ã§ãã
type RecFunc = | CallIsEven of int | CallIsOdd of int let isEven n = let mutable data = CallIsEven n (* æåã¯isEven'ãå¼ã³åºãã¦ããã®ã§ãCallIsEvenã渡ã *) let mutable res = true let mutable isCont = true while isCont do match data with (* isEven'ã0ã§å¼ã³åºããå ´åã«ç¸å½ *) (* 0ã¯å¶æ°ãªã®ã§ãresã«trueãå ¥ããisContãfalseã«ãã¦æ¬¡ã®ã«ã¼ãã«å ¥ããªãããã«ãã *) | CallIsEven 0 -> res <- true isCont <- false (* isEven'ã0以å¤ã§å¼ã³åºããå ´åã«ç¸å½ *) (* 次ã®ã«ã¼ãã§å¦çããdataãæ°ãã«ä½ãã ã *) | CallIsEven n -> data <- CallIsOdd (n - 1) (* isOddã0ã§å¼ã³åºããå ´åã«ç¸å½ *) (* 0ã¯å¥æ°ã§ã¯ãªãã®ã§ãresã«falseãå ¥ããisContãfalseã«ãã¦æ¬¡ã®ã«ã¼ãã«å ¥ããªãããã«ãã *) | CallIsOdd 0 -> res <- false isCont <- false (* isOddã0以å¤ã§å¼ã³åºããå ´åã«ç¸å½ *) (* 次ã®ã«ã¼ãã§å¦çããdataãæ°ãã«ä½ãã ã *) | CallIsOdd n -> data <- CallIsEven (n - 1) res
ç¸äºå帰ãèªå·±å帰ã«æ¸ãæãã¦ãã¾ãã°ãä»ã¾ã§è¦ãæ¹æ³ã使ã£ã¦while
ã«æ¸ãæãå¯è½ã§ãã
ã¾ã¨ã
çµå±ãF#ã§ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãå®å ¨ã«è§£æ±ºããããã«ã¯ã
- CPSã§ã¯ãªãå½¢ã®æ«å°¾å帰ã«æ¸ãæãã
- ãããé£ããå ´åã
while
ã§æ¸ãæãã
ã¨ããæ²ããçµæã«çµããã¾ããã ããã«ãç¶ç¶ã¢ãããã³ã³ãã¥ãã¼ã·ã§ã³å¼ã§å®è£ ããã¨ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ãã¦ãã¾ããã¨ããæ²ããç¾å®ããããã¾ããã
ãã®ãããªæ²ããç¾å®ã¨åãåã£ã¦å®è£ ãã(å®è£ ãã¦ãã)ã®ãFSharp.Quotations.Compilerã§ãã stackã¨whileã«ãã£ã¦ãF#ã®å¼æ¨ãILã«å¤æãã¦ãã¾ãã
ãã®ä¸é£ã®ã·ãªã¼ãºã¯ããã®ã©ã¤ãã©ãªãä½ãã«ããã£ã¦å¾ãç¥è¦(ã®å¤§ããåãã¦çæ¹ã®é¨å)ãå ¬éããããã«æ¸ãã¾ããã ããçæ¹ã®é¨å(ILçæå¨ãã®ç¥è¦)ã«ã¤ãã¦ããããæ°ãèµ·ãããã¾ã¨ãããã¨æãã¾ãã
ã¨ãããããç²ããã®ã§ãã®è¾ºã§ã»ã»ã»
*1:ãã¡ãããã®ä¾ã§ã¯ç°¡åã«æ«å°¾å帰é¢æ°ã«æ¸ãæãå¯è½ãªã®ã§ãæ«å°¾å帰é¢æ°ã«ãã¦ãã¾ãã®ãä¸çªæã£åãæ©ãã§ããããããããç°¡åã«ã¯æ«å°¾å帰ã«æ¸ãæãããªããã®ãå¤ãã®ã§ããã®å ´åã«ã©ãããã°ããããèãã¦ããã¾ãã
*2:ãå帰é¢æ°ã¯ãã¨æ¸ãã¾ããããå帰ã§ã¯ãªãåãªãé¢æ°å¼ã³åºããåæ§ã§ãã