从头开始定义列表函数而不是库函数
Posted
技术标签:
【中文标题】从头开始定义列表函数而不是库函数【英文标题】:defining list functions from scratch rather than library functions 【发布时间】:2019-12-07 20:03:06 【问题描述】:erlang 新手并试图解决这个问题,请帮助:
这个问题要求您定义四个对列表进行操作的函数。每个问题都给出了函数应该如何表现的示例;在每种情况下,再举两个例子说明你的函数应该做什么。您应该从头开始定义函数,而不是使用库函数。
1.1 编写一个函数,给定一个整数列表和一个整数,将返回一个包含所有大于该整数的元素的列表。例如, 更大的([1,2,3,4,5],3) 是 [4,5]。
【问题讨论】:
尝试开始更简单。你能写一个打印出列表中每个元素的函数吗?io:format("~w~n", [Number]).
当您弄清楚时,发布您的解决方案。当你开始学习 erlang 时,很难。你必须为每一行代码奋斗。但奋斗会教你很多!而且,如果你不能想出一个解决方案,这并不重要,这会让你觉得你失败了,但是一旦你在解决问题后看到了解决方案,它就会真正陷入......
这里有一个提示:编写一个接受问题中指定参数的函数。在该函数内部,使用相同的参数调用另一个函数,并添加一个空列表作为第三个参数。空列表可用于累积结果。
我一直在寻找如何操作列表等并提出了这个解决方案,但不完全确定它是否正确更大([],_) -> [];更大([X|Xs], A) -> 当 X>A -> [X|更大(A,Xs)];更大([_|Xs],A)-> 更大(A,Xs)。
【参考方案1】:
不要在 cmets 中发布代码。您可以编辑您的问题并将代码发布在底部(格式精美),然后发表评论,例如:@7stud, Can you take a another look?
您已接近,但您的代码无法编译,因为您有语法错误。这个:
bigger([X|Xs], A) -> when X>A ->
应该这样写:
bigger([X|Xs], A) when X>A ->
接下来,您将函数子句定义为将列表作为第一个参数,将数字作为第二个参数,但在某些情况下,您将列表作为第二个参数,将数字作为第一个参数来调用您的函数。当您使用数字作为第一个参数调用函数时,它与您在所有函数子句中定义为第一个参数的列表不匹配,因此您会收到 no function clause matching
错误。
以下是该错误的一个简单示例:
-module(a).
-compile(export_all).
go([Head|Tail], Number) ->
Head, Tail, Number.
在外壳中:
11> c(a).
a.erl:2: Warning: export_all flag enabled - all functions will be exported
ok,a
12> a:go(10, [1, 2, 3]).
** exception error: no function clause matching a:go(10,[1,2,3]) (a.erl, line 4)
Erlang 尝试将函数调用与函数定义相匹配,如下所示:
a:go(10, [1, 2, 3]).
| |
[Head|Tail] = 10 | | Number = [1, 2, 3]
V V
go([Head|Tail], Number) ->
整数10
无头无尾,所以匹配失败。同样:
13> [Head|Tail] = 10.
** exception error: no match of right hand side value 10
【讨论】:
【参考方案2】:实现目标的最简单方法是使用stdlib.lists
模块
如下:
bigger(L,I) -> lists:filter(fun(X) -> X > I end, L).
【讨论】:
【参考方案3】:bigger(L, I) when is_list(L), is_integer(I) ->
[X || X <- L, X > I].
不需要库函数。
【讨论】:
@yvvy19:这个解决方案是完全正确的,但是由于您是从 erlang 开始的,我认为您应该稍后再考虑这种语法,当您将掌握递归和模式匹配时。 @Pascal 我非常不同意。列表推导是语言和库函数列表的重要组成部分:filter/2 是使用列表推导实现的。为了掌握递归和模式匹配,我推荐以下练习:找到数字列表的最小或最大元素;计算列表元素的总和; ... @yvvy19:保护表达式“when is_list(L), is_integer(I)”可以去掉,功能不变。【参考方案4】:我想你可以使用一个简单的列表生成器,例如:
1> [X || X <- [1, 2, 3, 4, 5], X > 3].
[4,5]
或者您可以创建一个简单的函数,例如 bigger.erl:
-module(bigger).
-export([run/2]).
run([_|_] = L, N) when is_number(N) -> run(L, N, []);
run(_, _) -> error, badarg.
run([], _, Acc) -> lists:reverse(Acc);
run([H|T], N, Acc) when H > N -> run(T, N, [H|Acc]);
run([_|T], N, Acc) -> run(T, N, Acc).
在 Erlang shell 中:
1> c(bigger).
ok,bigger
2> bigger:run([1, 2, 3, 4, 5], 3).
[4,5]
或者您可以使用列表生成器创建函数,例如 bigger.erl:
-module(bigger).
-export([run/2]).
run([_|_] = L, N) when is_number(N) -> [X || X <- L, X > N];
run(_, _) -> error, badarg.
在 Erlang shell 中:
1> c(bigger).
ok,bigger
2> bigger:run([1, 2, 3, 4, 5], 3).
[4,5]
注意事项:使用列表生成器的功能更清晰,工作速度更快,因为我们一次遍历列表。在其他情况下 - 您将需要反向列表,这意味着列表将被抓取两次。
【讨论】:
以上是关于从头开始定义列表函数而不是库函数的主要内容,如果未能解决你的问题,请参考以下文章
使用 Buzz.js 音频从我停止的最后一个位置开始,而不是从头开始。 (ipad1)
Lua函数(function)语法与库函数 --math 表(table)