My question is why the following pattern returns 'match
even though (make-tree 0 null null)
is clearly not null?
#lang racket
(define-struct tree (val left right))
(match (make-tree 1 (make-tree 0 null null) null)
[(tree 1 null _) 'match]
[_ 'no-match])
I noticed changing the null
to '()
in the first pattern yields the correct(?) value. Why does this occur? Aren't null
and '()
equivalent? Thanks in advance.
According to https://docs.racket-lang.org/reference/match.html, identifiers in patterns has the following rule:
id
or(var id)
— matches anything, and bindsid
to the matching values.
In your case, null
is not evaluated to a value. Instead, it is recognized as an identifier shadowed by the value matched at that position, which is (make-tree 0 null null)
As already mentioned, a bare identifier will match anything because the purpose of an identifier in a match pattern is to create a new binding as a result of the match. Of course, null
is not a keyword in Racket, it’s just a binding exported by racket/base
, so it just gets bound as usual. In contrast, '()
is a quoted list literal, which can obviously be detected by match
and handled accordingly.
It is sometimes useful, though, to be able to compare values dynamically, in which case those values will be bound to identifiers. In this case, you can use the ==
match expander, which will compare the match to the value of an arbitrary expression. This would allow you to use null
if you wished:
#lang racket
(define-struct tree (val left right))
(match (make-tree 1 (make-tree 0 null null) null)
[(tree 1 (== null) _) 'match]
[_ 'no-match])
; => 'no-match
Of course, using '()
is probably clearer in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With