我正在尝试使用JavaScript中更实用的样式; 因此,我已经用for实用函数替换了for循环,例如map和reduce.但是,我没有找到while循环的功能替换,因为尾调用优化通常不适用于JavaScript.(根据我的理解,ES6可以防止尾调用溢出堆栈,但不会优化它们的性能.)
我解释了我在下面尝试过的内容,但TLDR是:如果我没有尾调用优化,那么实现while循环的功能方法是什么?
我尝试过的:
创建"while"实用程序功能:
function while(func, test, data) {
const newData = func(data);
if(test(newData)) {
return newData;
} else {
return while(func, test, newData);
}
}
Run Code Online (Sandbox Code Playgroud)
由于尾调用优化不可用,我可以将其重写为:
function while(func, test, data) {
let newData = *copy the data somehow*
while(test(newData)) {
newData = func(newData);
}
return newData;
}
Run Code Online (Sandbox Code Playgroud)
但是在这一点上,感觉就像我让我的代码更复杂/混淆使用它的任何人,因为我必须使用自定义实用程序功能.我看到的唯一实际优势是它迫使我使循环变得纯净; 但似乎只是使用常规while循环并确保我保持一切纯净是更直接的.
我还试图找出一种方法来创建一个模拟递归/循环效果的生成器函数,然后使用像find或reduce这样的实用函数迭代它.但是,我还没有想出一种可读的方法.
最后,用实用函数替换for循环使得我想要完成的更明显(例如,对每个元素做一件事,检查每个元素是否通过了测试等).然而,在我看来,while循环已经表达了我想要完成的事情(例如,迭代直到我们找到素数,迭代直到答案得到充分优化,等等).
所有这一切之后,我的整体问题是:如果我需要一个while循环,我正在以函数式编程,而且我无法访问尾调用优化,那么什么是最佳策略.
javascript recursion functional-programming while-loop tail-call-optimization
考虑这个例子:
const samples = ["foo", "bar"];
const excludeFoos = function(item) {
return item !== "foo";
}
const foos = samples.filter(excludeFoos);Run Code Online (Sandbox Code Playgroud)
如何传递其他参数excludeFoos?
例如:
const samples = ["foo", "bar"];
const exclude = function(item, str) {
return item !== str;
}
// obviously won't work but you get the point
const foos = samples.filter(exclude("foo"));
console.log(foos); // ["bar"]Run Code Online (Sandbox Code Playgroud)
我正在尝试对嵌套对象数组进行排序.它使用静态选择键,但我无法弄清楚如何动态获取它.
到目前为止,我已经有了这段代码
sortBy = (isReverse=false) => {
this.setState(prevState => ({
files: prevState.files.sort((a, b) => {
const valueA = (((a || {})['general'] || {})['fileID']) || '';
const valueB = (((b || {})['general'] || {})['fileID']) || '';
if(isReverse) return valueB.localeCompare(valueA);
return valueA.localeCompare(valueB);
})
}));
}
Run Code Online (Sandbox Code Playgroud)
此时键是硬编码的,['general']['orderID']但我想通过向函数添加一个keys参数来使这部分变为动态sortBy:
sortBy = (keys, isReverse=false) => { ...
Run Code Online (Sandbox Code Playgroud)
keys是一个嵌套键的数组.对于上面的例子,它将是['general', 'fileID'].
为实现这一目标需要采取哪些步骤?
注意:子对象可能是未定义的,因此我正在使用 a || {}
注2:我正在使用es6.没有外部包.
注意:这是作者删除的另一个问题的重新发布.这是原始问题:
我comp在Javascript中有这个polyvariadic 函数,并且想知道Haskell中是否有类似的实现是可能的.我最感兴趣comp的是:
const comp = f => Object.assign(
g => comp([g].concat(f)),
{run: x => f.reduce((acc, h) => h(acc), x)}
);
const inc = n => n + 1;
const sqr = n => n * n;
const repeatStr = s => n => Array(n + 1).join(s);
comp(repeatStr("*")) (inc) (sqr).run(2); // "*****"
comp(repeatStr("*"))
(inc)
(inc)
(inc)
(inc)
(inc).run(0); // "*****"
Run Code Online (Sandbox Code Playgroud)
comp构建一个异构数组,通常在Haskell中没有类型.我想这样的可变函数在其返回类型中必须是多态的.但是,到目前为止,这项任务超出了我的Haskell知识.任何线索都会有所帮助.
上下文
我使用Javascript运行时类型检查器,以便我可以comp以类型安全的方式在内部构建数组.它需要显式类型注释,并且仅支持参数和秩-2多态.
javascript haskell functional-programming variadic-functions function-composition
我对如何解决这个问题有点困惑。我需要所有素数才能返回 true。如果不返回 false——我看到我的逻辑包括 2 并且返回 0,所以它自动返回 false,因为 2 余数为 0。
function isPrime(num, div = 2) {
// BASE CASE:
if(num <= div ) return false; // IF num less than OR equal to 2 RETURN false
// IF num MOD has a remainder of zero
if(num % 2 === 0) return false // RETURN false
return true; // RETURN true
// RECURSIVE CALL:
return isPrime(num)
}
console.log(isPrime(1)); //-> false
console.log(isPrime(2)); //-> true
console.log(isPrime(3)); //-> true
console.log(isPrime(4)); //-> falseRun Code Online (Sandbox Code Playgroud)
一个简单的功能如下:
const L = a => L;
Run Code Online (Sandbox Code Playgroud)
形式
L
L(1)
L(1)(2)
...
Run Code Online (Sandbox Code Playgroud)
这似乎形成一个列表,但实际数据根本不存储,所以如果需要存储数据,例如[1,2],完成任务的最聪明的做法是什么?
const L = (a) => {
// do somthing
return L;
};
Run Code Online (Sandbox Code Playgroud)
我更喜欢这种简洁的箭头功能样式,并且不希望尽可能地破坏外部结构.当然,我理解一些外部结构修改是必需的,但我很好奇什么是可能的,特别是在功能风格而不是OO.
该规范仅用于存储功能链的数据.
有任何想法吗?谢谢.
最初最简单的方法是:
const L = (a) => {
L.val = a;
return L;
};
L.val = L;
Run Code Online (Sandbox Code Playgroud)
可以做一些,但没有数据积累.
{ [Function: L] val: [Circular] }
{ [Function: L] val: 1 }
{ [Function: L] val: 2 }
Run Code Online (Sandbox Code Playgroud)
注意:
每个列表应该独立于积累.
L(3)(4)
Run Code Online (Sandbox Code Playgroud)
将返回[3,4]不[2,3,3,4]与之前累积的其他列表.
javascript ×6
ecmascript-6 ×2
object ×2
recursion ×2
arrays ×1
chain ×1
haskell ×1
list ×1
primes ×1
sorting ×1
while-loop ×1