`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.
> ____________________
> Racket Users list:
>
http://lists.racket-lang.org/users
>
____________________
Racket Users list:
http://lists.racket-lang.org/users