为什么(匹配)中没有(dict(k v)......)模式?

时间:2017-08-07 08:12:14

标签: pattern-matching racket

这里的初学者问题,我只花了几个小时的语言。

球拍有dictionaries,由哈希表,对子列表等实现。(match)函数识别(hash-table (pat pat)...)(list-no-order pat...)等,但不识别(dict (pat pat)...) }。

我认为在dict接口上进行模式匹配会很有用,原因与接口完全相同。它的遗漏表明事实并非如此。谁能告诉我我错过了什么?如果我想对可能是哈希值或列表对的数据使用(match),我应该有两个子句吗?别的什么呢?

1 个答案:

答案 0 :(得分:0)

我最好的猜测:没有人觉得需要强大到足以为dict实施match模式。幸运的是match是可扩展的。表单define-match-expander可用于扩展match可以处理的模式集。

让我们说我们想要

(dict (k0 v0) (k1 v1))

表示与

相同
(or (hash-table (k0 v0) (k1 v1)
    (list-no-order (cons k0 v0) (cons k1 v1))

(对于具有两个以上键值对的模式类似) 然后我们可以像这样定义一个匹配扩展器:

(define-match-expander dict
  (λ (stx)
    (syntax-case stx ()
      [(_dict (key-pat val-pat) ...)
       #'(or (hash-table (key-pat val-pat)  ...)
             (list-no-order (cons key-pat val-pat) ...))])))

(dict ("a" a) ("b" b) ("c" c))现在可以理解像match这样的模式。

一个完整的例子:

#lang racket
(define-match-expander dict
  (λ (stx)
    (syntax-case stx ()
      [(_dict (key-pat val-pat) ...)
       #'(or (hash-table (key-pat val-pat)  ...)
             (list-no-order (cons key-pat val-pat) ...))])))

(define (keys+vals a-dict)
  (match a-dict
    [(dict ("a" a) ("b" b))
     (list a b)]))

(keys+vals (hash "a" 1 "b" 2))      ; gives '(1 2)
(keys+vals '(("b" . 5) ("a" . 4)))  ; gives '(4 5)