nmd*_*mdr 2 javascript recursion haskell
Haskell有一个takeWhile功能:
Prelude> takeWhile odd [1,3,5,7,8,9]
[1,3,5,7]
Run Code Online (Sandbox Code Playgroud)
只要应用谓词函数结果,它就会从列表中"获取"元素True.它变成了False,它停止了.
我们该如何实施呢?
这是我提出的Haskell递归方法:
takewhile::(a->Bool)->[a]->[a]
takewhile _ [] = []
takewhile f (x:xs) | f x == True = x : takewhile f xs
| otherwise = []
Run Code Online (Sandbox Code Playgroud)
只要谓词f x是True,它就会一直调用自身,否则它会返回一个空列表而不会调用它自己.
我可以为JavaScript提出以下实现.它有点冗长,并调用定义另一个函数来传递中间结果:
function takeWhile(f, xs) {
return take(f, xs, [])
}
function take(f, xs, arr) {
if(!xs || xs.length === 0) {
return arr
}
x = xs.shift()
if(f(x)) {
arr.push(x)
return take(f, xs, arr)
} else {
return arr
}
}
takeWhile((x)=>{
return x % 2 !== 0
},[1,3,5,7,9,11])
Run Code Online (Sandbox Code Playgroud)
有没有更好的想法在JavaScript中实现它?
如果你希望你takeWhile在HS中执行,即懒惰,你需要JS中的生成器:
function* takeWhile(fn, xs) {
for (let x of xs)
if (fn(x))
yield x;
else
break;
}
function* naturalNumbers() {
let n = 0;
while (true)
yield n++;
}
result = takeWhile(x => x < 10, naturalNumbers())
console.log([...result])Run Code Online (Sandbox Code Playgroud)
HS代码的直接端口也是可能的,但它只适用于物化数组(即,急切地):
// would be nice, but JS sucks ;(
// let takeWhile = (f, [x, ...xs]) => f(x) ? [x, ...takeWhile(f, xs)] : [];
let takeWhile = (f, xs) => xs.length ? takeWhileNotEmpty(f, xs) : [];
let takeWhileNotEmpty = (f, [x, ...xs]) => f(x) ? [x, ...takeWhile(f, xs)] : [];
let odd = x => x % 2
a = [1,3,5,7,8,9]
r = takeWhile(odd, a)
console.log(r)Run Code Online (Sandbox Code Playgroud)
实际上,正如@naomik 在这里展示的那样,有一种更好的方法来处理空列表:
let nil = {};
let takeWhile = (f, [x = nil, ...xs]) => (x === nil || !f(x))
? [] : [x, ...takeWhile(f, xs)];
console.log(takeWhile(x => x % 2, [1, 3, 5, 7, 8, 9]));Run Code Online (Sandbox Code Playgroud)
最后,你的初始尝试确实有一点,因为,与上面不同,它是尾递归,这是一件好事.它可以更简洁地写成
let takeWhile = (f, xs) => take1(f, xs, []);
let take1 = (f, xs, acc) => xs.length ? take2(f, xs, acc) : acc;
let take2 = (f, [x, ...xs], acc) => f(x) ? take1(f, xs, acc.concat(x)) : acc;
Run Code Online (Sandbox Code Playgroud)
两种方法的组合(即递归生成器)作为练习留下......