Fork me on GitHub
#clojure
<
2021-01-18
>
selfsame02:01:59

how likely is a collision on (hash (fn []))?

andy.fingerhut02:01:00

Are you interested academically, or are you planning on any part of your system relying upon that likelihood of collision? Depending on your goals, I'd recommend trying to avoid relying upon that likelihood of collision.

selfsame03:01:52

I built a system on it being unique and now it looks like it collides pretty frequently in practice

andy.fingerhut03:01:10

Relying on hash codes being unique is almost always a bad idea.

andy.fingerhut03:01:00

Unless you are talking about UUID's or something, with so many bits that are uniformly distributed that you can prove miniscule probabilities of collision.

andy.fingerhut03:01:52

With 32 bits of hash result, if they were uniformly randomly distributed, the so-called birthday paradox predicts about a 50% chance of at least one collision if you get up to 2^16 = 65,536 of them.

andy.fingerhut03:01:18

I have no reason to think that hash on Clojure functions is uniformly randomly distributed, though.

selfsame03:01:24

user=> (count (into #{} (take 10000 (repeatedly #(hash (fn [] ))))))
9988

selfsame03:01:05

yeah hmm i'll switch to a UUID of some sort

andy.fingerhut03:01:07

There are 2 collisions already.

ghadi03:01:16

These hashes are not cryptographically secure

ghadi03:01:54

collisions are frequent, and the output is 32-bit

emccue03:01:06

always assume hashCode returns 1 unconditionally

😂 3
emccue03:01:17

but map lookups are done via magic

didibus06:01:36

Oh wow, I missed that ClojureCLR now supports running on .Net Core, that's a big achievement. Seems everything works except AOT, and its up with Clojure 1.10 in featureset. https://groups.google.com/g/clojure-clr/c/MdxEbo0znAw

😮 12
👍 18
Paul07:01:43

yup... i'm happy that there's an effort on this.. i tried the repl, it works fine so far... hope the rest (compilation, etc) will follow... definetly watching this space :-)

didibus07:01:35

Ya, its been a while since I've used the .net ecosystem, but blazor and xamarin seem nice, and compilation to web assembly. So if ClojureCLR can get that working it could be interesting.

Paul07:01:33

yup... i'm learning F# on the side also... in fact, i have both fsharp and clojure slack channels opened.. hehe.. i hope both communities interact more and share... there's bolero for F# (to do blazor stuff).. maybe clojureclr could leverage that as well

simongray15:01:05

Do any libraries even exist for ClojureCLR?

jjttjj17:01:02

There's https://github.com/arcadia-unity/Arcadia but I think it might use its own clojureCLR fork

didibus18:01:50

Well you can use interop with the .Net ecosystem, similar to Java interop for Clojure JVM I believe.

didibus18:01:10

But I don't think ClojureCLR is widely used yet, so I haven't seen many Clojure based libs for it. I'd assume most lib that works for Cljs as well as Clojure would be easy enough to add support for ClojureCLR.

vemv17:01:00

Would you say this can be a normal scenario?

vemv17:01:50

I don't think I have a leak because all my app's objects/classes get eventually GCed. But I'm not sure if it's intended usage to have so many classloaders around

dpsutton17:01:25

are you using nrepl?

dpsutton17:01:21

can't remember the details but i think i remember that nrepl executions can result in new classloader objects. if you can compare against an instance using a socket server or just no repl at all you might see a large difference

👍 3
vemv17:01:54

Thanks for the pointer! It lead me to https://github.com/nrepl/nrepl/issues/8 which looks related, as I'm using [org.clojure/tools.nrepl "0.2.13"] which predates that issue (that dep is outdated, I know)

motform18:01:59

I am a bit confused to why I cannot use var in this function: (defn fname [f] (-> f var meta :name)) I understand the reader macro would not work (since it would be quoting the literal symbol in that ns?) and guess that it is because var is a special form that it fails, but why? Is the effect the same as if I would have used the reader macro?

andy.fingerhut18:01:43

var is a special form that works more like a macro than a function. (var f) also tries to look up f, not the value of f

👍 3
phronmophobic18:01:07

you probably want something like ns-resolve or resolve

phronmophobic18:01:17

although that will only work if you have the actual symbol at some point

noisesmith18:01:41

ns-resolve is very weird, but for whatever reason people always seem to grab that first rather than the simpler resolve

Matthew Curry01:01:59

Perhaps because of the name places its api doc next to the other namespace functions, the main docs being in alphabetical order. Obviously there’s the cheatsheet nowadays.

noisesmith07:01:32

that's true, and one thinks of it as a thing you're doing to a namespace

motform18:01:05

I have a vector of functions (a middleware stack) and I want to make a simple tapper that tap>s the context after each middleware, function name included, but maybe they have to be quoted to be resolvable?

phronmophobic18:01:32

I remember that someone was able to obtain a reasonable name from a function using a snippet they found in clojure's spec source code, but I can't seem to find it

noisesmith18:01:45

yeah, resolve needs a symbol, clojure doesn't really encourage function / symbol cross translation

phronmophobic18:01:57

maybe it was:

(defn- fn-sym [^Object f]
  (let [[_ f-ns f-n] (re-matches #"(.*)\$(.*?)(__[0-9]+)?" (.. f getClass getName))]
    ;; check for anonymous function
    (when (not= "fn" f-n)
      (symbol (clojure.lang.Compiler/demunge f-ns) (clojure.lang.Compiler/demunge f-n)))))

noisesmith18:01:41

IMHO you can kind of make that work, but there's likely a much simpler solution that doesn't require turning functions into symbols

noisesmith18:01:22

eg. providing the var rather than the function in the place where the middleware is added

phronmophobic18:01:24

agreed. it wouldn't be my first choice.

borkdude18:01:57

There is a hack like the above in the clojure.spec.alpha ns as well

borkdude18:01:57

oh it's literally that code ;)

phronmophobic18:01:38

I should have linked to it earlier, but I found it using jump to source in my editor before I could find it on github

borkdude18:01:06

@love.lagerkvist You can also attach metadata to clojure functions, or keep a map of fn obj -> name

motform19:01:59

oh, that a hack worthy of its name. @borkdude I guess that would be the saner choice, considering the number of functions is quite small. There is also (de-)munge I guess, not sure about the characteristics of that, but it sorta does what I want.

(require '[clojure.main :as m])

((fn [f] (-> f class str m/demunge)) util/qualified-keyed-ns-publics)
; => "class motform.bestå.util/qualified-keyed-ns-publics"

noisesmith19:01:12

the fact that "munge" is an ugly word is intentional

phronmophobic19:01:59

I like recommending dirty hacks and appealing to authority at the same time 😈

noisesmith19:01:40

the authorities are working under design constraints that probably don't apply to your project

phronmophobic19:01:00

if you only knew the power of the dark side