Reputation: 5020
> (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
How should I modify the match
pattern so the function above returns the same as (hash-ref h key 'do-something-else)
?
One problem seems to be that match
is auto-quoting key
, so that it literally matches 'key
rather than the value of the key
local variable. A second problem is that match hash-table
seems to want to match the entire hash table rather than just one key-value pair.
Upvotes: 2
Views: 561
Reputation: 8373
hash-ref
To duplicate the behavior of hash-ref
, you need to do two things:
(1) Use a key
pattern that only matches things that are equal to the value of the argument key
. You can do this with the ==
pattern:
(hash-table ((== key) value))
(2) Match hash tables where there are other entries other than key
. You can do this by adding _ ...
to match the other entries.
(hash-table ((== key) value) _ ...)
In context:
(define (f h key)
(match h
[(hash-table ((== key) value) _ ...) value]
[_ 'do-something-else]))
Makes (f h key)
behave like (hash-ref h key 'do-something-else)
.
Your pattern:
(hash-table (key value))
Does not autoquote the key
so that it literally matches 'key
. Instead it matches any hash table that has only one entry:
> (match (hash 'anything-goes 11)
[(hash-table (key value)) value]
[_ 'do-something-else])
11
That's because key
is interpreted as a pattern, and an identifier as a pattern matches anything. You can see this more clearly if you name it to something else and use it in the body:
> (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
When you write an identifier pattern that "happens" to have the same name as a local variable, it shadows it, just like this example:
> (let ([x "local variable"])
(match (list 1 2 3)
[(list 1 2 x)
x]))
3
The x
in the pattern matches anything, so it's matched against the 3
. The pattern shadows the x
, so when the body uses x
, it's referring to the 3
, and not the local variable. The local variable was never actually used because of this shadowing.
Upvotes: 2