您如何将哈希表与局部变量的值匹配?

时间:2018-09-10 03:15:33

标签: pattern-matching racket

> (define h #hash((a . 11) (b . 0)))
> (define (f h key)
    (match h
      [(hash-table (key value)) value]
      [_ 'do-something-else]))
> (f h 'a)
'do-something-else  ;; expect 11

如何修改match模式,使上面的函数返回与(hash-ref h key 'do-something-else)相同的内容?

一个问题似乎是match自动引用了key,因此它实际上匹配'key而不是局部变量key的值。第二个问题是match hash-table似乎要匹配整个哈希表,而不是仅一个键值对。

1 个答案:

答案 0 :(得分:1)

如何复制hash-ref的行为

要复制hash-ref的行为,您需要做两件事:

(1)使用key模式,该模式仅将与参数key的值等于相等的内容匹配。您可以使用== pattern

(hash-table ((== key) value))

(2)匹配哈希表,其中存在除key以外的其他条目。您可以通过添加_ ...使其与其他条目匹配来实现此目的。

(hash-table ((== key) value) _ ...)

在上下文中:

(define (f h key)
  (match h
    [(hash-table ((== key) value) _ ...) value]
    [_ 'do-something-else]))

使(f h key)的行为类似于(hash-ref h key 'do-something-else)

为什么您的第一次尝试不起作用

您的模式:

(hash-table (key value))

自动对key进行引号,使其与'key完全匹配。相反,它匹配任何只有一个条目的哈希表:

> (match (hash 'anything-goes 11)
    [(hash-table (key value)) value]
    [_ 'do-something-else])
11

这是因为key被解释为模式,而标识符作为模式可以匹配任何内容。如果将其命名为其他名称并在体内使用,则可以更清楚地看到这一点:

> (define (f h key-arg)
    (match h
      [(hash-table (key-pat value))
       (printf "key-arg = ~v\n" key-arg)
       (printf "key-pat = ~v\n" key-pat)
       value]))
> (f (hash 'anything-goes 11) 'a)
key-arg = 'a
key-pat = 'anything-goes
11

当您编写一个标识符模式“碰巧”与本地变量具有相同的名称时,它会遮盖,就像下面的示例一样:

> (let ([x "local variable"])
    (match (list 1 2 3)
      [(list 1 2 x)
       x]))
 3

模式中的x匹配任何内容,因此它与3匹配。该模式遮盖了x,因此当主体使用x时,它是指3,而不是局部变量。由于存在阴影,实际上从未使用过本地变量。