Fork me on GitHub
#clr
<
2023-02-26
>
dmiller04:02:49

And I pushed out ClojureCLR 1.12.0-alpha5 just now. This fixes a bug that someone told me about a long time ago, but I never had replicated. Well, a case finally came up. Literally. The case macro can fail because of the hashing of strings is not consistent across platforms. (And potentially on the same platform.) This is deliberate on the part of MS -- it's a security thing. case uses .GetHashCode in order to achieve its promise of constant time selection. (It does not do sequential tests of conditions in the manner of cond, say.) Hash instability means that when you compile in one place, the compiled code might not work properly somewhere else. for example, if you have

(defn f[x] (case :a 1 :b 2))
the compiled code is based on the hash codes of :a and :b at the time of compilation. if you run this code elsewhere and the hash code of :a has changed (it is currently based on the hash code of "a"), the call (f :a) can fail. Now, this is only a problem if you compile Clojure code in one place and consume the compiled code some other time/place. (And usually not then, actually. As I said, I've never run into it until this week.) That means Clojure code compiled to a DLL, i.e,, AOT-compilation, which means at present this is only a problem for ClojureCLR running on Framework 4.x. But hopefully one day not far from now we will have AOT-compilation back again. Possible solutions: (a) get rid of case entirely; (b) limit what case can have as switch constants -- if you want keywords and symbols, though, they will have to have their hash codes not depend on the String.GetHashCode(); (c) do (a) or (b) only under Framework 4.x; (d) re-implement GetHashCode where necessary. I chose option (d). it meant essentially unifying GetHashCode with hasheq -- i wrote about that [here](https://dmiller.github.io/clojure-clr-next/general/2023/01/18/making-a-hash-of-it.html), It took about an hour, plus testing and packaging. Maybe you worry about the same things MS worried about in establishing their hashing code. Let me know if you think one of the other options would be better. Of if you can think of a better option. At any rate, this is an alpha release, so test away. Nothing that can't be changed. Note: as I said, I've never run into it. I don't spend much time running under Framework at this point. And it's not a problem at present under .NET 6/7. When I run Clojure.Main461, it appears to be consistent. The situation we ran into this week was someone hosting a ClojureCLR REPL out of a C# host. And it manifested in the error-reporting code of the REPL which has several case expressions in it.

👍 7