【问题标题】:Erlang: is it possible to write the minimum function as a list fold?Erlang:是否可以将最小函数编写为列表折叠?
【发布时间】:2011-07-07 07:02:57
【问题描述】:

给定一个函数:

min(A, B)  when A =< B -> A;
min(_A, B)             -> B.

我可以在函数foldl中以与此类似的方式使用它吗:

lists:foldl(fun min/2, 0, [1,2,3,4,5,6,7,8,9,10])

我相信这是不可能的,因为我必须设置一个将与列表的其余部分进行比较的初始值,例如。 G。没有我能想到的身份功能。我说的对吗?

语法是用 Erlang 编写的,但非 Erlang 程序员也应该可以阅读。

【问题讨论】:

  • 你不能用head作为初始值吗?
  • 我想我可以,如下所示,这会在空列表上崩溃。
  • Yasir 和 Adam 的回答都很好,根据上下文,在空列表上崩溃可以接受也不能接受。顺便说一句,修复了您的示例,因此可以编译它。
  • 谢谢,@Peer。另外,我认为undefined 没有多大意义,例如,请参阅"Best explanation for Languages without Null"
  • @Yasir。我同意这一点。

标签: list functional-programming erlang higher-order-functions fold


【解决方案1】:
min(List) ->
    Min = fun(A,  B) when A < B -> A;
             (_A, B)            -> B end,
    lists:foldl(Min, undefined, List).

使用undefined 作为初始状态应该可以解决问题。为空列表返回 undefined,这有点像 API。

如果您希望它在空列表上崩溃,请改用此函数头:

min([Head|Rest]) ->
    Min = fun(A,  B) when A < B -> A;
             (_A, B)            -> B end,
    lists:foldl(Min, Head, Rest).

【讨论】:

  • 好答案!似乎第一个守卫 (undefined,B) -> B 是多余的。
  • 其实只是随机性它不会崩溃。我不知道结果是否是确定性的,但在我尝试过的示例中,任何数字和原子的比较都会返回更小的数字。
  • 传递undefined 有效,因为在处理异构类型时&lt; 运算符有一个明确定义的顺序。特别是,数字总是小于原子。在参考手册中查找订单函数。
【解决方案2】:
1> List = [42,13,25,3,19,20].
[42,13,25,3,19,20]
2> lists:foldl(fun(X, Y) -> erlang:min(X,Y) end, hd(List), tl(List)).   
3

使程序在空列表中崩溃,这是一种推荐的方法“让它崩溃”,而不是防御性编程。

【讨论】:

  • 糟糕,foldl 的最后一个参数应该是 tl(List)(列表尾部)。我希望我们有在 Haskell 中找到的函数 foldl1,这样我们就不用使用初始值了。
【解决方案3】:

Adam Lindberg 建议使用 undefined 作为初始值的缺点是它会为包含原子作为成员的列表生成奇怪的结果。 Erlang 具有所有对象的全局排序,因此 min 函数的一个很好的属性是可用于所有类型。

我认为在空列表上崩溃更合理。不同之处在于客户必须担心这种情况,而不必担心得到undefined 的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多