我正在尝试学习Erlang,来自C ++ / Java背景。这迫使我重新思考我的所有方法。
现在我正在尝试写一些返回列表中N个第一个元素的东西。现在它看起来像这样,虽然我不能在守卫或表达式中调用函数。 Erlang的做法是什么?
take([Xh|Xr],N,Xn) ->
if
len(Xn) /= N -> take(Xr,N,app(Xh, Xn));
len(Xn) == N -> Xn
end.
我之前也试过调用该函数,但这也不起作用:
take([Xh|Xr],N,Xn) ->
G = len(Xn);
if
G /= N -> take(Xr,N,app(Xh, Xn));
G == N -> Xn
end.
答案 0 :(得分:4)
通常在出现这种问题时,您需要切换到递归的思维方式,而不是您正在使用的迭代方法。这就是我要做的事情:
take(List, N) ->
take(List, N, []).
take(_List, 0, Acc) ->
lists:reverse(Acc);
take([H|T], N, Acc) ->
take(T, N - 1, [H|Acc]).
对于那些来自语言推广迭代方法的人来说,尝试和进入Erlang的方法非常普遍。问题是Erlang没有这样做的原语,因为它是一种函数式语言。所以你被迫以功能的方式去做,最后它通常是更优雅的方法。
答案 1 :(得分:4)
除了Fylke的解决方案之外,还有一些关于身体递归方法的说法:
take(_List,0) ->
[];
take([H|T],N) ->
[H|take(T,N-1)].
答案 2 :(得分:0)
你的方法本身并没有错,只需要一些帮助:
-module(foo).
-compile(export_all).
take([Xh|Xr],N,Xn) ->
G = length(Xn), %% This line had trouble. Use length/1 and end with , not ;
if
G /= N ->
take(Xr,N,app(Xh, Xn));
G == N ->
Xn
end.
app(X, L) ->
L ++ [X].
正如其他人提示的那样,你的方法不是Erlang惯用的,其他解决方案要好得多。另外,查找列表的源代码:split / 2
https://github.com/erlang/otp/blob/master/lib/stdlib/src/lists.erl#L1351