基本的Erlang - 守卫等函数调用的替代方案

时间:2011-10-29 14:11:43

标签: erlang

我正在尝试学习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.

3 个答案:

答案 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