ãã®è¨äºã¯ ã¯ã¦ãªã¨ã³ã¸ã㢠Advent Calendar 2024 ã® 2 æ¥ç®ã®è¨äºã§ãã
æ¨æ¥ã¯ id:hogashi ããã®ãquerySelectorAllã®çµæãmapãããã¨ãã¯Array.fromããã¨è¯ããã§ããã
ã©ããã趣å³ã§é¢æ°åè¨èªããã£ã¦ããè
ã§ãã
é·ããé¢æ°åè¨èªããã£ã¦ãªãã£ããç¡åå帰ãå¿ãããã¦ããã®ã§ããããããã¦ãä¸åç¹ã³ã³ããã¼ã¿ã§ç¡åå帰ãä½ãæµããæ¸ãä¸ãã¾ãã
以ä¸ãJavaScript ã®ææ³ã§æ¸ãããã³ã¼ãããã¨ã«èª¬æãã¦ããã¾ãã
ç®æ¬¡
- ç®æ¬¡
- ç¡åå帰ã¨ã¯
- ä¸åç¹ã³ã³ããã¼ã¿ (Z ã³ã³ããã¼ã¿)
- å®ç¨çãªè¨ç®ä¾: éä¹è¨ç®
- ä½ãèµ·ãã£ã¦ããï¼
- 2å¼æ°é¢æ°ã¸ã®å±é
- åã¯ã©ããªã£ã¦ãï¼
- ã¾ã¨ã
ç¡åå帰ã¨ã¯
ã¾ãã¯ã¢ããã¼ã·ã§ã³ã®ç¢ºèªããã
é常ãå帰é¢æ°ã¯ã
function sum(nums) { if (nums.length === 0) { return 0; } else { const num = nums.pop(); return num + sum(nums); } }
ã¨ãã£ãããã«ãé¢æ°å®ç¾©ã®ä¸ã§èªåèªèº«ãå¼ã¶ãã¨ã§å帰å¦çãè¨è¿°ã§ãã¾ãã
ãã®ä¾ã§ã¯ã return num + sum(nums);
ã®é¨åã§èªåèªèº«ãå¼ãã§ãã¾ããã
ã§ã¯ã以ä¸ã®ãããªå¶ç´ãã¤ã¡ã¼ã¸ãã¦ã¿ã¦ãã ããã
- é¢æ°ã«ååãä»ãããã¨ãã§ããªã
- é¢æ°å®ç¾©ã®ä¸ã§èªåèªèº«ãå¼ã¶ãã¨ãã§ããªã
ãã®ãããªå¶éã®ä¸ã§å帰ãæ¸ããããªã£ããã©ãããã°ããã§ããããï¼
ãããªè¦æã«å¿ããããã«äººé¡ã¯ ç¡åå帰 ã¨ããæ¹æ³ãç·¨ã¿åºãã¾ããããã®åã®éããé¢æ°åã«ä¾ããªãå帰å¦çã®æ¹æ³ã§ãã
ä»åã¯ç¡åå帰ã®å ·ä½çãªä½ãæ¹ãè¦ã¦ããã¾ãã
ä¸åç¹ã³ã³ããã¼ã¿ (Z ã³ã³ããã¼ã¿)
ãããªãã§ãã ä¸åç¹ã³ã³ããã¼ã¿ ã¨ãããã¤ãããã¾ãã
é¢æ°ãå¤æããé¢æ° (é«éé¢æ°) ã®å½¢ããã¦ãã¾ããå®ç¾©ã¯ããã§ãã
const fix = f => (g => g(g))(h => f(y => h(h)(y)));
ãªãã ããã¯ã£ã¦æãã§ãããè½ã¡çã㦠fix(f)
ãã©ã®ããã«å±éããããè¦ã¦ã¿ã¾ãããã
fix(f) â (f => (g => g(g))(h => f(y => h(h)(y))))(f) â (g => g(g))(h => f(y => h(h)(y))) â (h => f(y => h(h)(y)))(h => f(y => h(h)(y))) â f(y => (h => f(y => h(h)(y)))(h => f(y => h(h)(y)))(y)) = f(y => fix(f)(y))
fix(f) = f(y => fix(f)(y))
ã¨ããé¢ä¿ãè¦ãã¾ãããã¨ã¯ãããã¾ã ã¡ãã£ã¨ä½ããããã®ãåãããªãæãã®é¢æ°ã§ããã
ããã©ã¯ãã£ã¨å
·ä½çã« f
ã«ç¹å®ã®é¢æ°ã代å
¥ãã¦ã¿ã¾ãããã
f = next => x => next(x)
ã®å ´å
f = next => x => next(x)
ã®ã¨ãã® fix(f)(0)
ãèãã¾ãã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); // fix(f) = f(y => fix(f)(y)) const f = next => x => next(x); fix(f)(0) // fix(f) ã®å®ç¾©ãå±é â f(y => fix(f)(y))(0) // f ã®å®ç¾©ãå±é â (next => x => next(x))(y => fix(f)(y))(0) // ç¡åé¢æ°ãè©ä¾¡ãã â (x => (y => fix(f)(y))(x))(0) â (y => fix(f)(y))(0) â fix(f)(0)
ãªã㨠fix(f)(0)
ãè©ä¾¡ããã¨åã³ fix(f)(0)
ãç¾ãã¾ããã
é¢æ°ãå®è¡ãããã¨ããã¨åãé¢æ°ã®å®è¡ã«è¡ãçãã®ã§ããã®ããã°ã©ã ã¯å»¶ã
ã¨åãé¢æ°ãå¼ã³åºãç¶ãããã¨ã«ãªãã¾ãã
ãã® é¢æ°ã®å¼ã³åºãã延ã ã¨ç¹°ãè¿ããã ã¨ãããã¤ã¯ãå®éã«ãã£ã¦ã¿ã㨠å¦çãç¡éã«ã«ã¼ããã¦åæ¢ããªã ã¨ããæ±ãã«ãªãã§ãããã
ãããªé¢æ°ãå½¹ã«ç«ã¤ã®ãï¼
大ä¸å¤«ãããå°ãå¥ã®ä¾ãè¦ã¦ããã¾ãããã
f = next => x => next(x + 1)
ã®å ´å
f = next => x => next(x + 1)
ã®ã¨ããèãã¾ãããã
ããã»ã©ã¨ã¨ã¦ãä¼¼ã¦ãã¾ãã x + 1
ã¨è¶³ãç®ããã¦ãã¾ãã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); // fix(f) = f(y => fix(f)(y)) const f = next => x => next(x + 1); fix(f)(0) â f(y => fix(f)(y))(0) â (next => x => next(x + 1))(y => fix(f)(y))(0) â (x => (y => fix(f)(y))(x + 1))(0) â (y => fix(f)(y))(0 + 1) â fix(f)(0 + 1) â fix(f)(1)
fix(f)(0)
ãè©ä¾¡ãã㦠fix(f)(1)
ã«ãªãã¾ããã
å度 fix(f)(1)
ãè©ä¾¡ãã㨠fix(f)(2)
ã«ãªãã¾ããããã«ç¹°ãè¿ãã° fix(f)(3)
ã«ãªãã¾ãã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); // fix(f) = f(y => fix(f)(y)) const f = next => x => next(x + 1); fix(f)(0) â ... â fix(f)(1) â ... â fix(f)(1 + 1) â fix(f)(2) â ... â fix(f)(2 + 1) â fix(f)(3) â ...
åãé¢æ°ãå¼ã³åºãç¶ãã¦ããã¨ããç¹ã§ã¯å
ã»ã©ã®åãã§ããã®ä¾ã§ãé¢æ°ã®å®è¡ã¯åæ¢ããã«ã¨ã©ã¼ã«ãªãã¾ãã
ãã ä»åº¦ã¯å¼æ°ã®é¨åã§è¨ç®ãè¡ããã¦ããã®ã§ãä½ã å帰å¦çããã¦ããæã ãæã¦ã¾ããã
f = next => x => x > 1 ? x : next(x + 1)
ã®å ´å
ããä¸æ©è¸ã¿è¾¼ãã§æ¡ä»¶åå²ãå ãã¦ã¿ã¾ãããã
f = next => x => x > 1 ? x : next(x + 1)
ã«ã¤ãã¦èãã¾ãã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); // fix(f) = f(y => fix(f)(y)) const f = next => x => x > 1 ? x : next(x + 1); fix(f)(0) â f(y => fix(f)(y))(0) â (next => x => x > 1 ? x : next(x + 1))(y => fix(f)(y))(0) â (x => x > 1 ? x : (y => fix(f)(y))(x + 1))(0) â 0 > 1 ? 0 : (y => fix(f)(y))(0 + 1) â (y => fix(f)(y))(0 + 1) â fix(f)(0 + 1) â fix(f)(1) â ... â fix(f)(2) â ... â (x => x > 1 ? x : (y => fix(f)(y))(x + 1))(2) â 2 > 1 ? 2 : (y => fix(f)(y))(2 + 1) â 2
ã¤ãã«ç¡éã®é¢æ°å¼ã³åºããåé¿ã§ãã¾ããã
ãã©ã¦ã¶ã§å®è¡ãã¦ã¿ã¦ãåãçµæãå¾ããã¾ãã
f
ãã©ããªå¼ã ã£ããããä¸åº¦è¦ã¦ã¿ã¾ãããã
const f = next => x => x > 1 ? x : next(x + 1);
種æãããã㨠next(~)
ã®é¨åãå帰å¼ã³åºãã«ç¸å½ãã¦ãã¾ãã
æ¡ä»¶åå²ã追å ã㦠next(~)
ã å¼ã³åºããªã ãã¨ã§å帰ãæã¡åããã¨ãã§ããã®ã§ãã
ãã®æåãæç¶çã«æ¸ãã¦ã¿ãã¨ãããªæãã«ãªãã¯ãã§ãã
let x = 0; while (true) { if (x > 2) { return x; } else { x += 1; } }
ã©ãã§ãããï¼æ¡ä»¶åå²ãçµã¿è¾¼ãã å¼ f
ã渡ããã¨ã§ ä½ãå®ç¨çãªå¼ãçµã¿ç«ã¦ãããããªæ°ããã¦ãã ã¨æãã¾ãããï¼
å®ç¨çãªè¨ç®ä¾: éä¹è¨ç®
ããããä¸åç¹ã³ã³ããã¼ã¿ã使ã£ãå®ç¨çãªä¾ãè¦ã¦ããã¾ãããã
0以ä¸ã®èªç¶æ° n ã®éä¹ fact(n)
ãè¨ç®ãã¦ã¿ã¾ãã
ã¾ãéä¹é¢æ° fact
ãå®ç¾©ããããã®è£å©é¢æ° _fact
ã次ã®ããã«å®ç¾©ãã¾ãã
const _fact = next => n => n === 1 ? 1 : n * next(n - 1);
ããã fix
ã«ä¸ãã¦å±éãã¦ã¿ã¾ãããã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); // fix(f) = f(y => fix(f)(y)) const _fact = next => n => n === 1 ? 1 : n * next(n - 1); fix(_fact) â (f(y => fix(f)(y)))(_fact) â _fact(y => fix(_fact)(y)) â (next => n => n === 1 ? 1 : n * next(n - 1))(y => fix(_fact)(y)) â n => n === 1 ? 1 : n * (y => fix(_fact)(y))(n - 1)
ã¯ãï¼ ä¸é
æ¼ç®åã® else ç¯ã«æ³¨ç®ãã¦ãã ãã fix(_fact)(y)
ã¨ããå½¢ã§å帰çæ§é ãè¦ãã¦ãã¾ããã
n ã«ãå
·ä½çãªå¤ãå
¥ãã¦ã¿ã¾ãããã fix(_fact)(3)
ãå±éãã¾ãã
fix(_fact)(3) // fix ã®å®ç¾©ã«å¾ã fix(_fact) ãå±é â _fact(y => fix(_fact)(y))(3) // _fact ã®å®ç¾©ã«å¾ãå¼ãå±é â (next => n => n === 1 ? 1 : n * next(n - 1))(y => fix(_fact)(y))(3) â (n => n === 1 ? 1 : n * (y => fix(_fact)(y))(n - 1))(3) â 3 === 1 ? 1 : 3 * (y => fix(_fact)(y))(3 - 1) // ä¸é æ¼ç®åãè©ä¾¡ â 3 * (y => fix(_fact)(y))(3 - 1) // 3 - 1 ãè©ä¾¡ â 3 * (y => fix(_fact)(y))(2) â 3 * fix(_fact)(2) // 以ä¸ãç¹°ãè¿ã â 3 * _fact(y => fix(_fact)(y))(2) â 3 * (next => n => n === 1 ? 1 : n * next(n - 1))(y => fix(_fact)(y))(2) â 3 * (n => n === 1 ? 1 : n * (y => fix(_fact)(y))(n - 1))(2) â 3 * (2 === 1 ? 1 : 2 * (y => fix(_fact)(y))(2 - 1)) â 3 * 2 * (y => fix(_fact)(y))(2 - 1) â 3 * 2 * (y => fix(_fact)(y))(1) â 3 * 2 * fix(_fact)(1) â 3 * 2 * _fact(y => fix(_fact)(y))(1) â 3 * 2 * (next => n => n === 1 ? 1 : n * next(n - 1))(y => fix(_fact)(y))(1) â 3 * 2 * (n => n === 1 ? 1 : n * (y => fix(_fact)(y))(n - 1))(1) â 3 * 2 * (1 === 1 ? 1 : 1 * (y => fix(_fact)(y))(1 - 1)) â 3 * 2 * 1 â 6
ãµã
ããç²ããã¾ã§ãããfix(_fact)(3)
ã 3 * 2 * 1
ã«å±éãããæ§åãè¦ãã¦ãã¾ãã«éä¹è¨ç®ãã¦ããæãã§ããã
ãã¦fix(_fact)(n)
㧠n ã®éä¹ãè¨ç®ã§ãããã¨ãåãã£ãã®ã§ã
const fix = f => (g => g(g))(h => f(y => h(h)(y))); const _fact = next => n => n === 1 ? 1 : n * next(n - 1); const fact = fix(_fact);
ã¨ãã¦éä¹é¢æ° fact()
ãå®ç¾©ãããã¨ãã§ãã¾ããã
ä½ãèµ·ãã£ã¦ããï¼
ãããã㦠_fact
㨠fact
ã®å®ç¾©ãè¦ã¦ã¿ã¾ãããã
const _fact = next => n => n === 1 ? 1 : n * next(n - 1); const fact = fix(_fact);
_fact
ã®å®ç¾©ã«ã fact
ã®å®ç¾©ã«ãèªåèªèº«ãå¼ã³åºãè¨è¿°ã¯ããã¾ãããããä»åã®ãã¼ãéã èªåèªèº«ãå¼ã³åºããã¨ãªãå帰å¦çãå®ç¾ã§ãã ã¨ãããã¨ã«ãªãã¾ãã
ããã« _fact
ã®å®ç¾©ãããè¦ã¦ããã¨ä»®å¼æ°ã® next
ãã¾ãã§å帰å¼ã³åºãã®ããã«ä½¿ã£ã¦ãããã¨ãåããã¾ãã
å½¢å¼çãªç¥èã¨ãã¦ã¯ããã§ãã
fix
ã«é¢æ°g
ãä¸ãããã¨ã§é¢æ°f
ãå¾ãããf
ã¯é常ã®1å¼æ°é¢æ°ã¨ãã¦æ¯ãèãg
ã®ç¬¬ä¸ä»®å¼æ°next
ã®å¼ã³åºãã¯ãf
ã®å帰å¼ã³åºãã®ããã«æ¯ãèã
æ´ãã¦ãã¾ãããï¼å®éã«ç´ã«ææ¸ãã§éç®ãã¦ã¿ãã¨ããç解ãæ·±ã¾ãããç¥ãã¾ããã
2å¼æ°é¢æ°ã¸ã®å±é
å
ã»ã©ã®ä¾ã§è¦ã fact()
ã¯ãã ä¸ã¤ã®å¼æ° n
ãåã1å¼æ°é¢æ°ã§ããã
次ã«2å¼æ°é¢æ°ãç¡åå帰ã§æ¸ãä¾ãè¦ã¦ã¿ã¾ãããã
ä¾ã«åãä¸ããã®ã¯èªç¶æ° m
, n
ã®æ大å
¬ç´æ°ãæ±ããé¢æ° gcd(m, n)
ã§ãã
ã¦ã¼ã¯ãªããã®äºé¤æ³ ã使ã£ã¦è¨ç®ãã¾ãã
ã¾ãã¯ååå帰çã§ãã
const gcd = (m, n) => n === 0 ? m : gcd(n, m % n); gcd(1071, 1029); // => 21
ãããç¡åå帰ã§æ¸ãããã¨ããã§ããå°ã£ããã¨ãããã¾ããããã»ã©ç´¹ä»ããä¸åç¹ã³ã³ããã¼ã¿ fix
ã¯1å¼æ°é¢æ°ãä½ãã¨ãã«ãã使ããªãã®ã§ãã
åé¡ã®è§£æ±ºçã3ã¤ç´¹ä»ãã¾ãã
解決ç1: 2å¼æ°çã®ä¸åç¹ã³ã³ããã¼ã¿ã使ã
const fix2 = f => (g => g(g))(h => f((x, y) => h(h)(x, y)));
ãã®ä¸åç¹ã³ã³ããã¼ã¿ fix2
ã¯å
ã»ã©ã¾ã§è¦ã¦ãã fix
ã®2å¼æ°çã§ãã
使ãæ¹ã¯ fix
ã¨å¤ããã¾ããã
const fix2 = f => (g => g(g))(h => f((x, y) => h(h)(x, y))); const _gcd = next => (m, n) => n === 0 ? m : next(n, m % n); const gcd = fix2(_gcd); gcd(1071, 1029); // => 21
ãã¡ãã3å¼æ°é¢æ°ãæ¸ããããªã£ãã3å¼æ°çã® fix3
ãã4å¼æ°é¢æ°ãæ¸ããããªã£ãã4å¼æ°çã® fix4
ãå¿
è¦ã«ãªãã¾ããå°ãé¢åã§ããã
// 3å¼æ°ç const fix3 = f => (g => g(g))(h => f((x, y, z) => h(h)(x, y, z))); // 4å¼æ°ç const fix4 = f => (g => g(g))(h => f((x, y, z, w) => h(h)(x, y, z, w)));
解決ç2: ã«ãªã¼åðãã
ã«ãªã¼å ã¨ããæ¹æ³ã使ãã¨å¤å¼æ°é¢æ°ã¨åçã®ãã®ã1å¼æ°é¢æ°ã ãã§æ¸ããã¨ãå¯è½ã«ãªãã¾ãã
ä¾ã¨ã㦠Math.pow(x, y)
ã1å¼æ°é¢æ°ã§è¡¨ç¾ããã¨ã
const pow = x => y => Math.pow(x, y); Math.pow(2, 4); // => 16 pow(2)(4); // å¼ã³åºãæ¹ãå¤ããã®ã§æ³¨æ // => 16
pow
ã¯1å¼æ°é¢æ°ã§ãã
ãã ã pow(2)
ã®è¿ãå¤ãã¾ã1å¼æ°é¢æ°ã«ãªã£ã¦ãã¾ããå¼æ°ãä¸ã¤ãã¤æ¸¡ã㦠2åå¼ã³åºã ãã¨ã§2å¼æ°ã§ã®å¼ã³åºãã¨åçã®çµæãå¾ããã¾ãã
ã«ãªã¼åãã¦ãã¾ãã°å
¨ã¦ã®é¢æ°ã¯1å¼æ°é¢æ°ã«ãªãã®ã§ãå
ã»ã©ã® gcd
ã1å¼æ°çã® fix
ã使ã£ã¦å®ç¾©ã§ãã¾ãã
const fix = f => (g => g(g))(h => f(x => h(h)(x))); const _gcd = next => m => n => n === 0 ? m : next(n)(m % n); const gcd = fix(_gcd); gcd(1071)(1029); // ã«ãªã¼åã«ãã£ã¦å¼ã³åºãæ¹ãå¤ããã®ã§æ³¨æ // => 21
解決ç3: 1å¼æ°é¢æ°ã«ã¿ãã«ã渡ããã¨ã§å¯¾å¿ãã
ã2å¼æ°ãåãåãé¢æ°ãã¯ã2è¦ç´ ã®ã¿ãã«ã1ã¤åãåãé¢æ°ãã¨åçã§ãã
JavaScript ã«ã¯ã¿ãã«ãç¡ãã®ã§é
åã§ä»£ç¨ããã¨ã
const pow = ([x, y]) => Math.pow(x, y); Math.pow(2, 4); // => 16 pow([2, 4]); // å¼ã³åºãæ¹ãå¤ããã®ã§æ³¨æ // => 16
Math.pow(x, y)
ã¨åçã®è¨ç®ããã1å¼æ°é¢æ° pow([x, y])
ãå®ç¾©ã§ãã¾ããã
1å¼æ°çã® fix
ã使ã£ã¦ãã¿ãã«æ¸¡ãã® gcd
é¢æ°ãå®ç¾©ãã¦ã¿ã¾ãããã
const fix = f => (g => g(g))(h => f(x => h(h)(x))); const _gcd = next => ([m, n]) => n === 0 ? m : next([n, m % n]); const gcd = fix(_gcd); gcd([1071, 1029]); // ã¿ãã«æ¸¡ãã§å¼ã³åºã // => 21
ã©ã®æ¹æ³ã§ã2å¼æ°é¢æ°ã®ç¡åå帰ã«ä¸æã対å¿ã§ãã¦ãã¾ããã
åã¯ã©ããªã£ã¦ãï¼
ããã¾ã§è¦ã¦ããä¸åç¹ã³ã³ããã¼ã¿ fix
ãããã使ã£ã¦å®ç¾©ããç¡åå帰é¢æ°ã«é©åã«åä»ãã§ããã®ãæ°ã«ãªãã¾ãããï¼
ãªã㨠TypeScript ãªã fix
ã«é©åã«åãã¤ãããã¨ãå¯è½ã§ãã
ãã®ããã«ãªãã¾ãã
function fix<S, T>(f: (_: (_: S) => T) => (_: S) => T) { type U = (_: U) => (_: S) => T; return (g => g(g))((h: U) => f((y: S) => h(h)(y))); }
åä»ãã® fix
ã使ã£ã¦éä¹é¢æ° fact
ãæ¸ããä¾ã TypeScript Playground ã«ç¨æãã¾ããã
_fact
ã«æä½éã®å注éãã¤ããã ã㧠fact = fix(_fact)
ã®åãæ£ããæ¨è«ããã¦ãã¾ãã
ã¾ã¨ã
ä¸åç¹ã³ã³ããã¼ã¿ã使ãã¨æ±ºã¾ã£ããã¿ã¼ã³ã§ç¡åå帰ãå®ç¾ã§ãããã¨ãè¦ã¦ãã¾ããã
ã¾ãå¤å¼æ°é¢æ°ã«å¿ç¨ãããã¨ã TypeScript ã«ããåä»ãã«ã¤ãã¦ãç¥ããã¨ãã§ãã¾ããã
ããã§ç´¹ä»ããä¸åç¹ã³ã³ããã¼ã¿ãç¡åå帰ã¯è¨ç®æ©ç§å¦ã®å§ã¾ãã®é ããç 究ããã¦ãããã¼ãã§ããã³ã³ããã¼ã¿çè«ã確ç«ãã¦ãããå 人ã«æè¬ãã¾ãã
ç§ããã¯ä»¥ä¸ã§ãã
ä½è«
ãã®è¨äºã¯ä¸è¨ã®è¨äºã¨ã»ã¼åãå
容ã JavaScript ã§ç¼ãç´ãããã®ã§ãã
ä¸è¨ã®è¨äºã§ã¯ãµã³ãã«ã³ã¼ãã Haskell ã§æ¸ãã¦ãã¾ãããããHaskell ã§ãµã³ãã«ã³ã¼ãæ¸ãã¦èª°ãèªããããï¼ãã¨æã£ãã®ã§ JavaScript ã§æ¸ãç´ãã¾ããã
ä½è«2
ä¸åç¹ã³ã³ããã¼ã¿ã®åä»ãã«ã¤ãã¦ã¯ä¸è¨ã®è¨äºã大ãã«åèã«ããã¦ããã ãã¾ããã