如何在 ES6 中柯里化递归函数
How to curry a recursive function in ES6
我正在使用 javascript lambda 表达式进行一些函数式编程练习,并得出以下代码。该代码旨在 return 一个函数,该函数计算给定基值的给定数字的幂。我的代码如下;
const findUpper = base => (num, i = 0) => {
if (num < base) {
return i;
} else {
i++;
return findUpper(Math.round(num / base), i);
}
}
const findUpper2 = findUpper(2)
console.log(findUpper2(8)) //expected to have 3
这里的问题是,递归在第一次 findUpper
调用后就被破坏了,因为它 return 是一个函数。
我怎样才能使这个代码段起作用?
一种方式是这样
var findUpper = base => {
let fn = (num, i = 0) => {
if (num < base) {
return i;
} else {
i++;
return fn(Math.round(num / base), i);
}
};
return fn;
}
var findUpper2 = findUpper(2)
console.log(findUpper2(8))
在 fundUpper 中声明递归函数...递归调用 fn 而不是 findUpper
稍微"tidier"没有不必要地使用箭头函数
var findUpper = base => {
return function fn(num, i = 0) {
if (num < base) {
return i;
} else {
i++;
return fn(Math.round(num / base), i);
}
};
}
var findUpper2 = findUpper(2)
console.log(findUpper2(8))
虽然,使用=>代码可以像
一样简单
const findUpper = base => {
let fn = (num, i = 0) => (num < base) ? i : fn(Math.round(num / base), i + 1);
return fn;
}
这是你的错误
i++
return findUpper(Math.round(num / base), i);
您打算:
// don't forget, findUpper is a curried function
return findUpper(Math.round(num/base))(i + 1);
这是将程序编写为纯表达式的另一种方法
const findUpper = (base = 1) => (num = 0, exp = 0) =>
num < base
? exp
: findUpper (base) (num / base, exp + 1)
console.log (findUpper (2) (8))
使用通用 loop
/recur
过程,我们保持 findUpper
的参数干净,提高循环性能,并维护您想要的柯里化接口
const recur = (...values) =>
({ recur, values })
const loop = f =>
{
let acc = f ()
while (acc && acc.recur === recur)
acc = f (...acc.values)
return acc
}
const findUpper = (base = 1) => (num = 0) =>
loop ((n = num, exp = 0) =>
n < base
? exp
: recur (n / base, exp + 1))
console.log (findUpper (2) (8))
我正在使用 javascript lambda 表达式进行一些函数式编程练习,并得出以下代码。该代码旨在 return 一个函数,该函数计算给定基值的给定数字的幂。我的代码如下;
const findUpper = base => (num, i = 0) => {
if (num < base) {
return i;
} else {
i++;
return findUpper(Math.round(num / base), i);
}
}
const findUpper2 = findUpper(2)
console.log(findUpper2(8)) //expected to have 3
这里的问题是,递归在第一次 findUpper
调用后就被破坏了,因为它 return 是一个函数。
我怎样才能使这个代码段起作用?
一种方式是这样
var findUpper = base => {
let fn = (num, i = 0) => {
if (num < base) {
return i;
} else {
i++;
return fn(Math.round(num / base), i);
}
};
return fn;
}
var findUpper2 = findUpper(2)
console.log(findUpper2(8))
在 fundUpper 中声明递归函数...递归调用 fn 而不是 findUpper
稍微"tidier"没有不必要地使用箭头函数
var findUpper = base => {
return function fn(num, i = 0) {
if (num < base) {
return i;
} else {
i++;
return fn(Math.round(num / base), i);
}
};
}
var findUpper2 = findUpper(2)
console.log(findUpper2(8))
虽然,使用=>代码可以像
一样简单const findUpper = base => {
let fn = (num, i = 0) => (num < base) ? i : fn(Math.round(num / base), i + 1);
return fn;
}
这是你的错误
i++
return findUpper(Math.round(num / base), i);
您打算:
// don't forget, findUpper is a curried function
return findUpper(Math.round(num/base))(i + 1);
这是将程序编写为纯表达式的另一种方法
const findUpper = (base = 1) => (num = 0, exp = 0) =>
num < base
? exp
: findUpper (base) (num / base, exp + 1)
console.log (findUpper (2) (8))
使用通用 loop
/recur
过程,我们保持 findUpper
的参数干净,提高循环性能,并维护您想要的柯里化接口
const recur = (...values) =>
({ recur, values })
const loop = f =>
{
let acc = f ()
while (acc && acc.recur === recur)
acc = f (...acc.values)
return acc
}
const findUpper = (base = 1) => (num = 0) =>
loop ((n = num, exp = 0) =>
n < base
? exp
: recur (n / base, exp + 1))
console.log (findUpper (2) (8))