`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 <jarc...@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