[racket] Why does (case ...) quote its matching value expressions?

From: Vincent St-Amour (stamourv at ccs.neu.edu)
Date: Mon Dec 22 15:37:33 EST 2014

As Jon said.

For that kind of use case, I recommend `match`. It's better than `case`
in almost every (all?) respect.


At Mon, 22 Dec 2014 00:52:48 -0500,
Jon Zeppieri wrote:
> `case` is like C's `switch` (but unlike similar constructs in other
> C-like languages) in that the case labels must be known at compile
> time. This allows the compiler to generate especially efficient code.
> If the label values are densely distributed, a decent C compiler will
> usually generate a jump table. Racket's `case` can't do that, since
> it's not implemented at a low-enough level, but it can generate, in
> the best case, a vector lookup followed by an open-coded binary
> search. In the worst case, it will use a hash table lookup followed by
> an open-coded binary search. (If the number of constant labels is
> below a set threshold, then `case` will just test them in order,
> exactly as if you'd written a `cond` expression. That's what
> `case/sequential-test` does.)
> C's switch does, however, allow the use of constant *expressions* as
> case labels, so you can have something like `case FOO % 3`, where `FOO
> % 3` can be computed at compile-time. (In your example of `case x %
> 3`, unless the value of `x` is known at compile time, it would be
> illegal in C, though legal certain languages that use a similar
> syntax.) Racket's `case`, on the other hand, only allows plain-old
> values.
> This is limiting sometimes. For example, to get the very best
> performance out of `case`, you need to use either fixnums or chars,
> but if you're creating, say, a state machine, you probably want to use
> symbolic names for your states. In C, you'd define an integer constant
> and use the symbolic name as your case label. You can't do that with
> Racket's `case`, however; if you want to use symbolic names, then
> you'll actually be representing your states with symbols rather than
> fixnums.
> At any rate, if you actually need to do runtime computation in your
> state labels, then neither C's `switch` nor Racket's `case` are
> appropriate.
> On Sun, Dec 21, 2014 at 11:58 PM, J Arcane <jarcane at gmail.com> wrote:
> > Up with a horrible ear-ache this morning I decided to include a FizzBuzz
> > example in Heresy, the Racket #lang I've been working on, and ran into an
> > unexpected behavior in the (case ...) statement.
> >
> > In many languages with case, you can make the testing value a constant, and
> > then make the matching clauses actual calculations which then match against
> > that constant. So when doing FizzBuzz in C-like languages you can do
> > something like "switch 0" and then "case x % 3" for the matching clauses.
> >
> > It turns out this doesn't work in Racket, because Racket quotes the values
> > in the matching clauses so they do not evaluate. Specifically, it narrows
> > down to doing this in (case/sequential-test ...): #`(equal? v 'k)
> >
> > I can implement an alternate version that works as I expect (and will
> > probably include it in Heresy) just by removing that quote in my version,
> > but I was curious as to the reasoning behind this behavior and if perhaps
> > there's some explanation for it that I may've missed.
> >
> > Any insights appreciated,
> > John Berry
> >
> >
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
> >
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.