2014-11-14 81 views
0

我已經開始學習二郎最近和整個以下錯誤就試圖pattren比賽Erlang的模式匹配誤差

下面的表達式是工作的罰款:

{A,_,[B|_],{B}}={abc,23,[22,x],{22}}. 
Resulting in 
A = abc 
B = 22 

以下表達式不工作:

{A,_,[_|B],{B}}={abc,23,[22,x],{x}}. 
Is resulting in 
** exception error: no match of right hand side value {abc,23,[22,x],{x}} 

但是,如果我將[22,x中的','替換爲|像下面它的工作發現和邊界x到B

{A,_,[_|B],{B}}={abc,23,[22|x],{x}}. 
{abc,23,[22|x],{x}} 
B. 
x 

任何關於這個解釋將不勝感激。

很多感謝

+1

[_ | Whatever]可能意指字面意義上的* anything *,所以它不能匹配,因爲'_'可以消耗/匹配任何東西,包括匹配的整個元素。這意味着「任何東西,隨後是」無論什麼「 - 我們在這裏沒有定義」。 '[22 |無論]'還是任何'[FiniteThing | _]'意思是「具體和有限的東西,後面是'Whatever'」,可以匹配,因爲它可以完全匹配和消耗列表的第一部分。 IOW,「任何事物」匹配/消耗*一切*,而一個特定和有限的事物只能表現自己。 – zxq9 2014-11-14 16:36:20

回答

1

運算符|用於遞歸定義列表:[A|B]表示您將元素A添加到現有列表BA是結果列表中的第一個元素,稱爲頭,B是名爲尾的其餘部分。 B也可以拆分成頭部和尾部,並且該過程可以繼續,直到尾部等於空列表[]

該運算符是列表元素之間的分隔符,因此[A,B]是包含2個元素AB的列表。

的2個運營商可以被組合:[A,B,C|D]是至少3個元素,這是ABC和尾部D它可以是空的列表。

在您的測試中,您使用了另一種語法:[23|x]; 23可以是列表中的元素(實際上,任何erlang項都可以是列表的元素),但x是原子,不能是列表尾。這樣做會破壞列表的遞歸定義,這種結構並不經常被使用,並被稱爲不正確的列表。

  • 當你匹配[_|B][_,x],分配[x]B當你匹配[_|B][_|x]不匹配x在表達

  • 後,分配xB這的確匹配x後面的表達方式,但正確的方式應該是

  • {A,_,[_|B],{B}}={abc,23,[22,x],{[x]}}.

+0

非常感謝您的詳細解釋 – 2014-11-14 16:42:30

1

你需要看就怎麼做的|運營商更緊密的作品。它基本上是列表的頭部,這是一個元素,並返回列表的尾部,這是其餘的部分。和「all」一樣,建議tail也是一個列表。它可能是一個元素列表,它甚至可能是空列表,但仍然會是一個列表。

> [Head| Tail] = [23,x]. 
[23,x] 
> Head. 
23 
> Tail 
[x]. 

所以在你的模式匹配,分配是尾[x],並且不是試圖模式匹配的簡單x。這就是失敗。

在旁註:您可以使用|運算符創建新列表,但應謹慎操作。因爲您可以創建improper list(並且您使用[23 | x])。這就是爲什麼你的「修復」工作。

如果你想匹配兩個元素列表上,你可以用

[A, B] = [23, x]. 

做明確的,但如果列表有更多或更少的元件,這將失敗。

如果您只想匹配兩個第一個元素,則仍然可以使用|運算符。

> [A, B | Rest] = [23, x]. 
[23, x] 
> A. 
23 
> B. 
x 
> Rest. 
[]. 

而這隻會失敗,只有一個元素或空列表。