Racket编程指南——12 模式匹配

12 模式匹配

match表支持对任意Racket值的模式匹配,而不是像regexp-match那样的函数,将正则表达式与字符及字节序列比较(参见正则表达式)。

(match target-expr
  [pattern expr ...+] ...)

match表获取target-expr的结果并试图按顺序匹配每个pattern。一旦它找到一个匹配,对相应的expr序列求值以得到匹配(match)表的结果。如果pattern包括模式变量(pattern variables),他们被当作通配符,并且在expr里的每个变量被绑定给的被匹配的输入片段。

大多数Racket的字面表达式可以用作模式:

> (match 2
    [1 'one]
    [2 'two]
    [3 'three])

'two

> (match #f
    [#t 'yes]
    [#f 'no])

'no

> (match "apple"
    ['apple 'symbol]
    ["apple" 'string]
    [#f 'boolean])

'string

conslistvector这样的构造器,可以用于创建模式,以匹配配对、列表和向量:

> (match '(1 2)
    [(list 0 1) 'one]
    [(list 1 2) 'two])

'two

> (match '(1 . 2)
    [(list 1 2) 'list]
    [(cons 1 2) 'pair])

'pair

> (match #(1 2)
    [(list 1 2) 'list]
    [(vector 1 2) 'vector])

'vector

struct绑定的一个构造器也可以用作一个模式构造器:

> (struct shoe (size color))
> (struct hat (size style))
> (match (hat 23 'bowler)
   [(shoe 10 'white) "bottom"]
   [(hat 23 'bowler) "top"])

"top"

不带引号的,在一个模式中的非构造器标识是模式变量(pattern variables),它在结果表达式中被绑定,除了_,它不绑定(因此,这通常是作为一个泛称(笼统描述)):

> (match '(1)
    [(list x) (+ x 1)]
    [(list x y) (+ x y)])

2

> (match '(1 2)
    [(list x) (+ x 1)]
    [(list x y) (+ x y)])

3

> (match (hat 23 'bowler)
    [(shoe sz col) sz]
    [(hat sz stl) sz])

23

> (match (hat 11 'cowboy)
    [(shoe sz 'black) 'a-good-shoe]
    [(hat sz 'bowler) 'a-good-hat]
    [_ 'something-else])

'something-else

省略号,写作...,就像在列表或向量模式中的克莱尼星号(Kleene star):前面的子模式可以用于对列表或向量元素的任意数量的连续元素的任意次匹配。如果后跟省略号的子模式包含一个模式变量,这个变量会匹配多次,并在结果表达式里被绑定到一个匹配列表中:

> (match '(1 1 1)
    [(list 1 ...) 'ones]
    [_ 'other])

'ones

> (match '(1 1 2)
    [(list 1 ...) 'ones]
    [_ 'other])

'other

> (match '(1 2 3 4)
    [(list 1 x ... 4) x])

'(2 3)

> (match (list (hat 23 'bowler) (hat 22 'pork-pie))
    [(list (hat sz styl) ...) (apply + sz)])

45

省略号可以嵌套以匹配嵌套的重复,在这种情况下,模式变量可以绑定到匹配列表的列表中:

> (match '((! 1) (! 2 2) (! 3 3 3))
    [(list (list '! x ...) ...) x])

'((1) (2 2) (3 3 3))

quasiquote表(见《准引用:quasiquote》以获取更多关于它的信息)也可以用来建立模式。而一个通常的准引用(quasiquote)表的非引用部分意味着普通的racket求值,这里非引用部分意味着回到普通模式匹配。

因此,在下面的例子中,with表达模式是模式并且它被改写成应用表达式,在第一个实例里用准引用作为一个模式,在第二个实例里准引用构建一个表达式。

> (match `{with {x 1} {+ x 1}}
    [`{with {,id ,rhs} ,body}
     `{{lambda {,id} ,body} ,rhs}])

'((lambda (x) (+ x 1)) 1)

有关更多模式表的信息,请参见racket/match

match-letmatch-lambda的表支持位置模式,否则必须是标识。例如,match-letlet归纳为解构绑定(destructing bind):

> (match-let ([(list x y z) '(1 2 3)])
    (list z y x))

'(3 2 1)

有关这些附加表的信息,请参见racket/match

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值