3

我剛開始學習函數式編程,我發現自己很困惑模式匹配(我使用SML)的概念。例如下面的表達式在有序列表中插入一個元素:SML中的模式匹配 - 代表一個列表(x :: y)

fun insert (n,nil) = [n] 
    | insert (n, L as x::l) = 
    if(n < x) then n::L 
    else x::(insert(n,l)) 

如何將列表L表示爲x :: l?我知道x指的是列表中的第一個元素,其餘的是l,但我不知道該怎麼調用這個構造或者如何使用它。我讀了很多,但我找到的所有文檔都沒有提到這一點。這是另一個不使用'as'關鍵字的例子。

(*returns a list with the sum of each element added of two lists added together*) 

fun addLists (nil,L) = L 
| addLists (L,nil) = L 
| addLists (x::xs,y::ys) = 
    (x + y)::(addLists(xs,ys)) 

謝謝你的幫忙!

+1

L只是第二個參數,只要它具有格式x :: l – Ingo

回答

5

對於這裏的insert功能:

fun insert (n,nil) = [n] 
    | insert (n, L as x::l) = 
    if(n < x) then n::L 
    else x::(insert(n,l)) 

| insert (n, L as x::l)部分是將進行匹配的圖案。 L as x::l被稱爲作爲模式。它使我們能夠:

  1. 模式匹配對非空列表,其中x是列表的頭部和l是列表
  2. 指整個匹配列表x::l與名稱的尾部L

這類似於(儘管不是完全相同)這樣做的:

| insert (n, x::l) 

除了第在,如果你這樣做,insert功能將變爲:

fun insert (n,nil) = [n] 
    | insert (n, x::l) = 
    if(n < x) then n::x::l 
    else x::(insert(n,l)) 

所以在非作爲圖案使用L as x::l作爲模式的最大優點是,它允許我們指整個列表,而不僅僅是它的頭和尾部,並且當我們需要參考整個列表時避免額外的列表構造。觀察兩段代碼的唯一區別是n::Ln::x::l。由於我們在第一個insert函數中使用L as x::l作爲模式,因此我們可以執行n::L而不是n::x::l。這避免了一個操作(也稱爲cons操作)。

至於這樣的:

fun addLists (nil,L) = L 
| addLists (L,nil) = L 
| addLists (x::xs,y::ys) = 
    (x + y)::(addLists(xs,ys)) 

對於第二圖案| addLists (x::xs,y::ys),在無處我們重建它後面的代碼清單x::xsy::ys,所以我們不需要爲圖案。你可以寫這樣的:

fun addLists (nil,L) = L 
| addLists (L,nil) = L 
| addLists (ListX as x::xs, ListY as y::ys) = 
    (x + y)::(addLists(xs,ys)) 

,它會仍然工作,只是我們不指ListXListY這裏,因此這兩個作爲模式是不必要的。

+0

非常感謝! – macalaca

相關問題