【问题标题】:Why is there no (dict (k v)...) pattern in (match)?为什么 (match) 中没有 (dict (k v)...) 模式?
【发布时间】:2018-01-14 11:34:44
【问题描述】:

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

Racket 具有 dictionaries,由哈希表、对列表等实现。(match) 函数可识别 (hash-table (pat pat)...)(list-no-order pat...) 等,但不能识别 (dict (pat pat)...)

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

【问题讨论】:

    标签: pattern-matching racket


    【解决方案1】:

    我的最佳猜测:没有人觉得有必要为match 实现dict 模式。幸运的是 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) ...))])))
    

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

    一个完整的例子:

    #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)
    

    【讨论】:

      猜你喜欢
      • 2014-06-02
      • 2017-07-07
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 2013-08-04
      • 1970-01-01
      相关资源
      最近更新 更多