Javascript 一个叫做奋斗的高阶函数怎么样?

Javascript 一个叫做奋斗的高阶函数怎么样?,javascript,functional-programming,erlang,Javascript,Functional Programming,Erlang,想象一下,你妻子让你去买些坎皮恩花。因为这是一种稀有的花,你不确定你是否能在隔壁的花店找到它。所以你必须检查镇上的每一家花店,并向他们索要露营地。但事实上,有些花店有公用电话号码,你可以通过电话询问。他们中的一些人有网站,而其中的一些人你必须走进去 所以你从最简单的解决方案开始你的探索。关键是你要以一种独特的方式检查每一家花店,就像你和他们交谈的方式,或者你走到他面前的路。如果我们从代码的角度讲,这是几个函数;每家商店一个功能 因此,在编程世界中,您必须为10个可能的解决方案编写10个不同的查询

想象一下,你妻子让你去买些坎皮恩花。因为这是一种稀有的花,你不确定你是否能在隔壁的花店找到它。所以你必须检查镇上的每一家花店,并向他们索要露营地。但事实上,有些花店有公用电话号码,你可以通过电话询问。他们中的一些人有网站,而其中的一些人你必须走进去

所以你从最简单的解决方案开始你的探索。关键是你要以一种独特的方式检查每一家花店,就像你和他们交谈的方式,或者你走到他面前的路。如果我们从代码的角度讲,这是几个函数;每家商店一个功能

因此,在编程世界中,您必须为10个可能的解决方案编写10个不同的查询函数。下一步是一个接一个地尝试列表中所有可能的解决方案,一旦你得到肯定的答案/回复/返回,你将停止任务并给出答案

我认为这是一个常规,最有可能像过滤器、映射和减缩器一样,我相信我是对的

那吃点这样的怎么样

在erlang中:

-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,no
Array.prototype.find
Array.prototype.filter
只有在所有数据都位于一个位置或至少共享一个数据结构时才有效(将它们合并为具有一个数据源)。我说的是一种需要不同函数体的情况,其中一个可能是
ans=>ans!==未定义
,但不是全部。@T4rk1n不知何故,但不确切。因为
Promise.race
同时执行所有可能的解决方案,并返回从这些异步调用的promises中获得的第一个
resolve
。在这里,我们需要一个顺序/优先级。您知道,即使在找到答案之后,您的reducer版本也需要重复的比较步骤。我知道做一个简单的
ans!==未定义的
调用,但无论如何它都是多余的,我知道问题是这种循环没有中断,因为在非命令式代码中根本没有中断。函数式语言通常通过惰性支持短路。JavaScript是经过严格评估的,因此您需要使用JavaScript的一些必要功能(一个为您提供此功能的库)编写它,或者像最初一样使用递归。这仅在函数返回
true
false
时才起作用。我相信OP希望能够从函数返回任何值,并返回第一个非
false
值。至少OP的Erlang和JS代码就是这样做的(JS代码返回第一个未定义的值)。