"Eric Schulte" <schulte.e...@gmail.com> writes: > Hi, > > The following case statement > > #+begin_src clojure > (defn buggy-case [n] > (case (int n) > 0 :null > 1 :load > 0x70000000 :loproc)) > #+end_src > > throws the following error > > No distinct mapping found > [Thrown class java.lang.IllegalArgumentException] > > However removing any of the cases alleviates the problem. Am I missing > something obvious, or is this a bug in the case statement?
Interesting! I hadn't looked at how case was implemented before. It takes the keys and then finds a shift and bitmask which can be used to differentiate them with a minimum number of contiguous bits. The private function clojure.core/min-hash is used to do this. For example if you have the case keys 0x400, 0x500 and 0x7700 then: (min-hash [0x400 0x500 0x7700]) => [8 3] Which means bit-shift-right by 8 bits and then bitwise-and by 3. So if we apply that to our keys we get: (map #(shift-mask 8 3 %) [0x400 0x500 0x7700]) => (0 1 3) The resulting values are then turned into a jump table which the tableswitch JVM instruction dispatches on. The maximum size of the mask is 14 bits, presumably as that's the maximum the tableswitch instruction supports. Now the problem in your case is there's no simple shift mask that is unique. If we write your keys in binary then the problem is obvious: 0000000000000000000000000000000 0000000000000000000000000000001 1110000000000000000000000000000 ^-------------^ 0000000000000000000000000000000 0000000000000000000000000000001 1110000000000000000000000000000 ^-------------^ There's no way to position the 14-bit mask (the ^-------------^ in my diagram) to obtain a unique result. It looks like Java's switch statement falls back to the lookupswitch instruction which is apparently usually implemented with a binary search. That doesn't seem to be implemented in Clojure and would in any case be breaking the "constant time" contract the case macro's docstring mentions (binary search is logarithmic time). -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en