2011-10-29 59 views
3

我想學習Erlang,來自C++/Java背景。這迫使我重新思考我所有的方法。基本Erlang - 替代函數調用警衛等

現在我試圖寫一些返回列表的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

這個問題是幾乎相同[這個問題](http://stackoverflow.com/questions/7902881/erlang-element-and -list),它有更明確的答案。 – rvirding

回答

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沒有這樣做的原語,因爲它是一種功能語言。所以你不得不以功能的方式來完成它,最後它通常是更優雅的方法。

+0

我認爲這是一個解決它的遞歸方式,只有一個附加條件。那麼,我想我還沒有深入思考。謝謝! – Rickard

+1

它是遞歸的,因爲你在自稱自己,但是你正在計數而不是下降,這就是爲什麼我稱它爲迭代。這使得很難確定何時達到基本情況。 – Fylke

4

除了Fylke的解決方案,也有一些對身體遞歸方法可說:

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

我知道'_'可以標記一個不相關的變量,但是它在這個意義上做了什麼,如'_List'? – Rickard

+3

它標記一個*名爲*無關變量。關鍵是你可以暗示讀者,我們在那個位置拿一份清單,而不僅僅是一些東西。 Erlang內部對待它們的方式相同。 –

+0

@Rickard它通常被稱爲* do not care *變量,因爲它絕對不是無關緊要的,因爲它必須在那裏,但我們不在乎它有什麼價值。 '_'變量永遠不會綁定到一個值,因此它可以在一個模式中多次使用而沒有意義。通常情況下,編譯器會在你將一個變量綁定在外時使用它來發出警告,但是如果變量以'_'開頭,就像上面的'_List'一樣,它不會發出這樣的警告。 **注意**這樣一個變量是一個正常的變量,並且以**的方式作爲一個整體,只有'_'在語言中非常特殊。 – rvirding

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慣用的,其他解決方案要好得多。此外,查找用於列出的源代碼:分流/ 2

https://github.com/erlang/otp/blob/master/lib/stdlib/src/lists.erl#L1351