模式匹配在计算机科学中,模式匹配是检查给定记号序列中,是否存在某种模式的组成部分的行为。与模式识别相反,匹配通常必须是精确的。模式通常具有序列或树状结构的形式。模式匹配的用途包括:输出一个模式在一个记号序列中的位置(如果有的话),输出匹配模式的一些组成部份,以及用一些其他的记号序列替换匹配模式(即搜索和替换)。 概述在一些编程语言中,模式被用作一种通用工具,基于数据的结构来处理数据,包括C#[1]、 F#[2]、Haskell[3]、ML、Python[4]、Ruby[5]、Rust[6]、Scala[7]、Swift[8]、仓颉[9]和Mathematica的符号式Wolfram语言,它们拥有表达树状结构的特殊语法,和基于它的条件执行和值检索的语言构造。 经常可以给出逐个尝试的交替式模式,它产生强力的条件编程构造[10]。模式匹配有时包括对守卫子句的支持[11]。 字符序列也就是字符串,经常使用正则表达式来描述,并使用像回溯这样的技术来进行匹配。解析算法经常依赖模式匹配来将字符串变换成语法树[12][13]。 历史具有模式匹配构造的早期编程语言包括:COMIT(1957年)、SNOBOL(1962年)、具有树状模式的Refal(1968年)、Prolog(1972年)、SASL(1976年)、NPL(1977年)和KRC(1981年)。 很多文本编辑器支持各种的模式匹配:支持正则表达式查找的QED编辑器,和在查找中支持 简单模式在模式匹配中,最简单的模式是一个明确的值或一个变量。例如,考虑采用Haskell语法的一个简单函数,这里函数参数不放在圆括号内但用空白分隔, f 0 = 1
这里的 f n = n * f (n-1)
这里的第一个 通配符模式(通常写为 在Haskell中,下面的代码定义了一个代数数据类型 data Color = ColorConstructor Integer String
例如,要得到 integerPart (ColorConstructor theInteger _) = theInteger
要得到字符串部份: stringPart (ColorConstructor _ theString) = theString
这些函数可以通过Haskell的数据记录语法自动创建。 模式匹配还可应用来过滤特定结构的数据。例如,在Haskell中可以使用列表推导式进行这种过滤: data ABint = A Int | B Int
[A x|A x <- [A 1, B 1, A 2, B 2]]
求值结果为: [A 1, A 2]
序列模式从上述原始模式,可以建造更加复杂的模式,通常采用的方式,相同于通过组合其他值来建造值。区别在于,具有变量和通配符部份,模式不建造成一个单一值,而是匹配一组值,它们是具体元素和允许在模式结构内变化的元素的组合。 在Haskell和一般的函数式编程语言中,列表是主要数据结构,它通常被定义为一种典型的代数数据类型: data List a = Nil | Cons a (List a)
列表被定义为空列表,或一个元素构造在一个现存的列表上。在Haskell语法下写为: [] -- 空列表
x:xs -- 元素x构造在列表xs之上
具有一些元素的一个列表的结构,就是 head (element:list) = element
这里断定了 在这个例子中,我们没有用到 head (element:_) = element
树状模式树状模式一般用来匹配由递归数据类型生成的复杂的树状结构,比如编程语言抽象语法树。它通过开始于一个节点,指定某些分支以及节点,并且通过变量或通配符留下一些不指定,来描述一个树的一部份。 下面是在OCaml下,定义一个红黑树和在元素插入后再平衡的函数的例子: type color = Red | Black
type 'a tree = Empty | Tree of color * 'a tree * 'a * 'a tree
let rebalance t = match t with
| Tree (Black, Tree (Red, Tree (Red, a, x, b), y, c), z, d)
| Tree (Black, Tree (Red, a, x, Tree (Red, b, y, c)), z, d)
| Tree (Black, a, x, Tree (Red, Tree (Red, b, y, c), z, d))
| Tree (Black, a, x, Tree (Red, b, y, Tree (Red, c, z, d)))
-> Tree (Red, Tree (Black, a, x, b), y, Tree (Black, c, z, d))
| _ -> t (* the 'catch-all' case if no previous pattern matches *)
字符串模式迄今最常用形式的模式匹配涉及字符串。在很多编程语言中,使用特定的字符串语法来表示正则表达式,它是描述字符串的模式。 在Haskell中,如下模式匹配有两个字符并且开始于 ['a', _]
可以介入符号式实体,来表示一个字符串的很多不同类的有关特征。在Haskell中,可以使用守卫来进行匹配: [letter, digit] | isAlpha letter && isDigit digit
它将匹配首个字符是一个字母,接着的是一个数字的字符串。 符号式字符串操纵的主要好处,是它可以与编程语言的其余部份完全的集成,而非成为一个独立的、专用的子单元。这个语言的整体能力,可以放大到建造模式自身,或分析和变换包含它们的程序。 Python的模式匹配定义在Python版本3.10中[16],模式匹配的语法应该是: match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
其中 例子def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _: #省略此行及下一行以创造一个没有通配符的模式匹配
return "Something's wrong with the Internet"
如果省略最后两行,当 同理,模式匹配也可用于 class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print(f"Y={y} and the point is on the y-axis.")
case Point(x=x, y=0):
print(f"X={x} and the point is on the x-axis.")
case Point():
print("The point is located somewhere else on the plane.")
case _:
print("Not a point")
和其他语言中的模式匹配一样,Python中也可以在匹配的语句中使用通配符: match test_variable:
case ('warning', code, 40):
print("A warning has been received.")
case ('error', code, _):
print(f"An error {code} occurred.")
引用
外部链接![]() 維基教科書中的相關電子教程:Pattern matching
|
Portal di Ensiklopedia Dunia