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

时间:2017-07-20 21:33:48

标签: javascript functional-programming erlang

想象你的妻子要你去买一些坎皮恩花。因为这是一种罕见的花,你不确定你是否能找到隔壁的花店。因此,你必须检查镇上的每一家花店,并要求他们的营地。但事实上,一些花店有公共电话号码,你可以通过电话询问。其中一些有网站,其中一些你必须走进去。

所以你从最简单的解决方案开始你的任务。关键是你以一种独特的方式检查每一家花店,就像你和他们交谈的方式,或者你走路去找那家伙的路。如果我们以代码方式谈话,这些是几个功能;每个商店一个功能。

因此在编程世界中,您必须为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);
}

你认为它不够通用,无法成为内置的高阶函数吗?

PS:代码工作正常,没有必要修复它。问题是,为什么它不是内置函数?

3 个答案:

答案 0 :(得分:4)

确切的问题是什么?

strugle(Input, Solutions) ->
  lists:any(fun(X) -> X(Input) end, Solutions).

这是Erlang必需品。或者,如果您希望返回第一个非假值。

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.

答案 1 :(得分:1)

这听起来非常像Array.prototype.find,除了你想要的返回值是find看到的第一个真值,而不是产生真值的元素。

您可以使用Array.prototype.reduce来完成此任务:

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函数往往是非常通用的。更具体的功能更适合实用程序库。

答案 2 :(得分:1)

在Scheme中,您可以这样编写代码:

// some from SRFI-1, also called ormap in some dialects
(define (struggle input solutions)
  (some (lambda (f) (f input)) solutions))

似乎JavaScript得到Array.prototype.some而Erlang有lists:any/2,但两者都有缺陷,因为它们不会返回真值但只有true所以你只知道是否它找到了答案而不是答案。

在JS中,制作some的版本与Scheme的工作方式相同很简单。我对Erlang不确定。