2014-01-15 100 views
4

我一直在研究一個示例代碼,我不明白髮生了什麼,我試圖更容易理解的例子,並得到他們,但在這其中,我被卡住:問題的理解順序二郎山

seq([X, X | Xs]) -> [X | seq(Xs)]; 
seq([X, Y | Xs]) -> [X, Y | seq(Xs)]; 
seq(_) -> []. 

當我用[1,1,1,2,2,2,3]在shell中運行它[1,1,2,2]。我一直試圖通過將它寫在紙上來理解這些步驟,但我陷入了半途而廢的狀態。

我將不勝感激所有解釋我在這裏發生的步驟! :) /Eri。

+0

我假設你想得到[1,2,3]作爲輸出?請說明預期的結果。 – kjw0188

+0

我不想得到任何特定的輸出,我只想了解erlang是如何工作的,我上面介紹的代碼就是一個例子。當我用[1,1,1,2,2,2,3]運行時,我得到[1,1,2,2],我只想知道它是如何得到的[1,1,2,2 ]以瞭解如何執行這些步驟。所以我想有人向我解釋步驟。 –

回答

11

好了,我們開始與[1,1,1,2,2,2,3]列表。

在第一次調用seq,二郎將匹配前兩個元素11seq第一「條款」 - seq([X, X | Xs])。 這將初始化將成爲最終返回值的列表,[1, seq(Xs)]。此時Xs將被綁定到值[1,2,2,2,3]。如果你想知道爲什麼在XS列表的開頭沒有兩個1,那是因爲我們在[X, X | Xs]上匹配/綁定了其中的兩個。

返回值 = [1 | ?](?在剩餘遞歸進行評估)
兩個X = [1,2,2,2,3]

在第二次調用seq,二郎將匹配輸入列表1的前兩個元素和2到第二條款seq([X, Y | Xs])。然後,我們從這次運行中「返回」列表[X,Y]或[1,2],並用Xs = [2,2,3]調用下一次迭代。

返回值 = [1 | [1, 2 | ?]] < - 看看遞歸嵌套列表?
兩個X = [2,2,3]

在第三呼叫,前兩個元素是相同的了,所以二郎再次運行所述第一子句。 seq([X, X | Xs]) -> [X | seq(Xs)]。作爲評估的一部分,我們返回一個2值,並致電seq([3])

返回值 = [1 | [1, 2 | [2 | ?]]]
兩個X = [3]

最後,最後的情況下。我們的名單[3]不匹配[X, X | Xs]也不[X, Y, Xs],所以二郎將運行我們的包羅萬象:seq(_) -> []._將匹配任何東西,而不是值綁定到任何局部變量,所以我們在這裏做的是返回一個空列表[]

我們的最終回報值是:[1 | [1, 2 | [2 | []]]]。如果你將它評估爲erl repl,你會發現它與列表[1,1,2,2]相同,後者是前者的語法糖。

+1

非常感謝!你解釋得很好,我現在瞭解它是如何發展的,真棒! –

4

跟蹤可以幫助你一點點:

1> dbg:tracer(). 
{ok,<0.35.0>} 
2> dbg:p(self(), [c]). 
{ok,[{matched,[email protected],1}]} 
3> dbg:tpl({test, seq, 1}, [{'_',[],[{return_trace}]}]). 
{ok,[{matched,[email protected],1},{saved,1}]} 
4> test:seq([1, 1, 1, 2, 2, 2, 3]). 
(<0.33.0>) call test:seq([1,1,1,2,2,2,3]) 
(<0.33.0>) call test:seq([1,2,2,2,3]) 
(<0.33.0>) call test:seq([2,2,3]) 
(<0.33.0>) call test:seq([3]) 
(<0.33.0>) returned from test:seq/1 -> [] 
(<0.33.0>) returned from test:seq/1 -> [2] 
(<0.33.0>) returned from test:seq/1 -> [1,2,2] 
(<0.33.0>) returned from test:seq/1 -> [1,1,2,2] 
[1,1,2,2] 
+1

如果該函數是尾遞歸的,它將更有幫助,因爲生成的值在跟蹤中也可見。 –