我刚刚开始学习函数式编程,我发现自己对模式匹配的概念感到非常困惑(我正在使用SML)。以下面的表达式为例,在有序列表中插入一个元素:
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))
感谢您的帮助!
答案 0 :(得分: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
被称为 as pattern 。它允许我们:
x
是列表的头部,l
是列表的尾部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
作为非模式模式的一大优势在于它允许我们引用整个列表,而不仅仅是它的头部和尾部,并且在我们需要时避免使用额外的列表构造引用整个列表。请注意,2段代码中唯一的区别是n::L
和n::x::l
。由于我们在第一个L as x::l
函数中使用了模式insert
,因此我们可以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::xs
和y::ys
,因此我们不需要作为模式。你可以这样写:
fun addLists (nil,L) = L
| addLists (L,nil) = L
| addLists (ListX as x::xs, ListY as y::ys) =
(x + y)::(addLists(xs,ys))
并且它仍然可以使用,除了我们在这里没有引用ListX
或ListY
,因此这两个模式是不必要的。