Javascript 一个叫做奋斗的高阶函数怎么样?
想象一下,你妻子让你去买些坎皮恩花。因为这是一种稀有的花,你不确定你是否能在隔壁的花店找到它。所以你必须检查镇上的每一家花店,并向他们索要露营地。但事实上,有些花店有公用电话号码,你可以通过电话询问。他们中的一些人有网站,而其中的一些人你必须走进去 所以你从最简单的解决方案开始你的探索。关键是你要以一种独特的方式检查每一家花店,就像你和他们交谈的方式,或者你走到他面前的路。如果我们从代码的角度讲,这是几个函数;每家商店一个功能 因此,在编程世界中,您必须为10个可能的解决方案编写10个不同的查询函数。下一步是一个接一个地尝试列表中所有可能的解决方案,一旦你得到肯定的答案/回复/返回,你将停止任务并给出答案 我认为这是一个常规,最有可能像过滤器、映射和减缩器一样,我相信我是对的 那吃点这样的怎么样 在erlang中:Javascript 一个叫做奋斗的高阶函数怎么样?,javascript,functional-programming,erlang,Javascript,Functional Programming,Erlang,想象一下,你妻子让你去买些坎皮恩花。因为这是一种稀有的花,你不确定你是否能在隔壁的花店找到它。所以你必须检查镇上的每一家花店,并向他们索要露营地。但事实上,有些花店有公用电话号码,你可以通过电话询问。他们中的一些人有网站,而其中的一些人你必须走进去 所以你从最简单的解决方案开始你的探索。关键是你要以一种独特的方式检查每一家花店,就像你和他们交谈的方式,或者你走到他面前的路。如果我们从代码的角度讲,这是几个函数;每家商店一个功能 因此,在编程世界中,您必须为10个可能的解决方案编写10个不同的查询
-export([struggle/2]).
struggle(Input, Solutions) ->
struggle(Input, Solutions, false).
struggle(_, [], false) ->
false;
struggle(Input, [Solution|OtherSolutions], false) ->
struggle(Input, OtherSolutions, Solution(Input));
struggle(_, _, Answer) ->
Answer.
或在javascript中:
function struggle(input, solutions)
{
let strgl = (input, solutions, acc) => {
if (solutions.length === 0 && acc === undefined) return undefined;
if (acc === undefined) return strgl(input, solutions.slice(1), solutions[0](input));
return acc;
};
return strgl(input, solutions, undefined);
}
难道你不认为它足够普遍,可以成为一个内置的高阶函数吗
附:代码运行良好,无需修复。问题是,为什么它不是一个内置函数?这听起来很像,只是您想要的返回值是
find
看到的第一个truthy值,而不是生成truthy值的元素
您可以使用来完成此任务:
function struggle(input, solutions) {
return solutions.reduce((ans, solution) =>
ans !== undefined ? ans : solution(input)
, undefined);
}
必须这样写,就像:
function struggle(input, solutions) {
for (const solution of solutions) {
const ans = solution(input);
if (ans !== undefined) {
return ans;
}
}
return undefined;
}
这听起来不像是一个内置函数,因为它不够通用。这里有两个步骤:(1)映射解决方案,(2)测试值是否可接受。内置JavaScript函数往往是非常通用的。更具体的函数更适合于实用程序库。在Scheme中,您可以这样编写代码:
//有些来自SRFI-1,在某些方言中也称为ormap
(定义(输入解决方案)
(一些(lambda(f)(f输入))解决方案)
JavaScript和Erlang似乎都有缺陷,因为它们都不返回truthy值,而只返回true
,因此您只能知道它是否找到了答案,而不是答案是什么
在JS中,制作与Scheme相同的
some
版本非常简单。我不确定Erlang的具体问题是什么
strugle(Input, Solutions) ->
lists:any(fun(X) -> X(Input) end, Solutions).
这是Erlang essentials。或者,如果希望返回第一个非false值
strugle(Input, Solutions) ->
any_non_false(fun(X) -> X(Input) end, Solutions).
any_non_false(F, L) ->
try lists:any(fun(X) ->
case F(X) of
false -> false;
Y -> throw({return, Y})
end
end, L)
catch {return, X} -> X end.
所以有点像
Promise.race
?我不知道Erlang,但你在寻找解决方案吗?solutions.map(f=>f(input)).find(ans=>ans!==undefined)
@4castle,noArray.prototype.find
和Array.prototype.filter
只有在所有数据都位于一个位置或至少共享一个数据结构时才有效(将它们合并为具有一个数据源)。我说的是一种需要不同函数体的情况,其中一个可能是ans=>ans!==未定义
,但不是全部。@T4rk1n不知何故,但不确切。因为Promise.race
同时执行所有可能的解决方案,并返回从这些异步调用的promises中获得的第一个resolve
。在这里,我们需要一个顺序/优先级。您知道,即使在找到答案之后,您的reducer版本也需要重复的比较步骤。我知道做一个简单的ans!==未定义的
调用,但无论如何它都是多余的,我知道问题是这种循环没有中断,因为在非命令式代码中根本没有中断。函数式语言通常通过惰性支持短路。JavaScript是经过严格评估的,因此您需要使用JavaScript的一些必要功能(一个为您提供此功能的库)编写它,或者像最初一样使用递归。这仅在函数返回true
或false
时才起作用。我相信OP希望能够从函数返回任何值,并返回第一个非false
值。至少OP的Erlang和JS代码就是这样做的(JS代码返回第一个未定义的值)。