【问题标题】:Basic Erlang - Alternatives to function calls in guards etcBasic Erlang - 守卫等中函数调用的替代方案
【发布时间】:2012-09-15 11:04:16
【问题描述】:

我正在尝试学习 Erlang,来自 C++/Java 背景。这迫使我重新思考我所有的方法。

现在我正在尝试编写返回列表的前 N ​​个元素的内容。现在它看起来像这样,虽然我不能在警卫或 if 表达式中调用函数。 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.

【问题讨论】:

  • 这个问题与this question 几乎相同,后者有一些更明确的答案。

标签: erlang


【解决方案1】:

一般遇到此类问题,您需要切换到递归的思维方式,而不是您正在使用的迭代方法。这就是我要做的:

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 没有这样做的原语,因为它是一种函数式语言。所以你不得不以函数式的方式来做,最终它往往是更优雅的方法。

【讨论】:

  • 我认为这是一种递归的解决方法,只是添加了一个条件。好吧,我想我还没有进入这个想法。谢谢!
  • 嗯,它递归的,因为你在调用自己,但是你是在向上计数而不是向下计数,这就是我称之为迭代的原因。这使您更难确定您何时达到了基本情况。
【解决方案2】:

除了 Fylke 的解决方案之外,还有一些关于体递归方法的说法:

take(_List,0) ->
  [];
take([H|T],N) ->
  [H|take(T,N-1)].

【讨论】:

  • 我知道'_'可以标记一个不相关的变量,但它在这个意义上是做什么的,比如'_List'?
  • 它标记了一个 named 不相关的变量。关键是你可以暗示读者我们在那个位置列出一个列表,而不仅仅是一些东西。 Erlang 内部以同样的方式对待它们。
  • @Rickard 它通常被称为 don't care 变量,因为它绝对不是无关紧要的,因为它必须存在,但我们不在乎它有什么价值。 _ 变量永远不会绑定到一个值,因此它可以在一个模式中多次使用而没有意义。通常,当您只绑定变量而不使用它时,编译器会发出警告,但是如果变量以 '_' 开头,如上面的_List 中那样,它不会发出这样的警告。 注意 这样的变量是一个普通变量,并且在每一种方式中都表现得像一个,只有_在语言中是真正特殊的。
【解决方案3】:

您的方法本身并没有错,只是需要一点帮助:

-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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-05
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多