Fork me on GitHub
#cljs-dev
<
2020-12-22
>
niwinz13:12:08

Hello folks! Just to confirm, there are something special that breaks clojurescript hash-map when keys are js/Symbol ?

niwinz13:12:25

Seems like they are broken:

> (def s1 (js/Symbol "1"))
#'cljs.user/s1
> (contains? (array-map s1 :a) s1)
true
> (contains? (hash-map s1 :a) s1)
false

dnolen13:12:02

@niwinz symbols don't have good equality semantics in JS, but I suppose if this works for Object it should work for Symbol

dnolen13:12:21

though that should probably be tested first, whether even Object works

dnolen13:12:47

i.e. reference types as keys should work, and that's what Symbol is

niwinz13:12:53

symbols in js are unique, this is why we are using them, is the fastest way to generate a value that is different of other values

dnolen13:12:16

sure though why you're using isn't really that important to this problem 🙂

dnolen13:12:32

just check the behavior of #js {} as a key or #js [], if it works

dnolen13:12:53

then Symbol("foo") should work as well

dnolen13:12:23

note if you don't hold onto this somehow you'll never be able to retrieve the value again

niwinz13:12:50

js object works as expected

dnolen13:12:31

@niwinz feel free to open a JIRA ticket w/ these details

niwinz13:12:31

the symbol in js acts as value and not a reference as far as i know

dnolen13:12:08

> Symbol("foo") === Symbol("foo")
> false

dnolen13:12:11

in the Node REPL

dnolen13:12:25

no sensible equality semantics

dnolen13:12:28

then it's not a really a value

niwinz13:12:53

yeah this is the real purpose

niwinz13:12:56

of symbols

dnolen13:12:00

i.e. I wouldn't use this as key myself in CLJS maps

niwinz13:12:17

they are different of cljs symbols

niwinz13:12:26

if you want all the time the same symbol for "name"

niwinz13:12:37

you need to use Symbol.for("name")

dnolen13:12:33

ah k which looks like it returns some kind of interned thing

niwinz13:12:34

> Symbol.for("a") === Symbol.for("a")
true

dnolen13:12:43

yes I just checked

dnolen13:12:58

probably this is an easy one? I think we don't have a hashing case for symbols or something like that

niwinz13:12:06

this is why i said that symbols are the fastest way to create a unique value

dnolen13:12:24

sure but not interested in the detail, just the bug 🙂

niwinz13:12:53

hmm i think i don't have access to jira, should I need to write this on http://ask.clojure.org?

niwinz14:12:48

i confirm, i don't have access to jira for open the issue; that is ok, just tell me where i can open the issue

dnolen14:12:37

yeah Symbols aren't currently hashable (we cannot add hash property w/ goog.getUid for random objects). So thinking we should probably get the string value of the Symbol and hash that?

dnolen14:12:39

other ideas welcome

dpsutton14:12:00

wouldn't that break their equality semantics? if Symbol("a") != Symbol("a") the hash can't be based on the string value?

favila15:12:11

What about putting the guid in a WeakMap keyed by symbol? nm, looks like symbols are not allowed as weakmap keys

favila15:12:13

that seems like a strange limitation

favila15:12:37

symbols are allowed as keys in Maps though, so symbols could still have a guid hash value in there instead of a WeakMap. The downside is that symbols not created from the global registry (i.e. Symbols made by Symbol(…) not Symbol.for(…)) will never be GC’d. Symbols made by Symbol.for(…) are already not GCed so no loss there.

dpsutton15:12:02

did i read correctly that while they can be keys in maps they "are not enumerable in for...in iterations."

favila15:12:30

Maps don’t have a useful for-in. The point of them is to be able to safely store any key without worrying about colliding with the properties of the js object that implements Map itself. you can use for-of though

andy.fingerhut01:12:25

It is acceptable correctness-wise for things that are not equal to have the same hash value -- just leads to poor hashing performance if you have too many such objects with the same hash value in the same hashable collection simultaneously.

andy.fingerhut01:12:03

You would get terrible hashing performance if the hash of every object/value was 0, but it would not break equality semantics.

borkdude15:12:51

I am relying on symbols not being identical? to each other even when created with the same string in CLJS code:

(identical? (symbol "a") (symbol "a")) ;;=> false

borkdude16:12:37

what do you mean with different symbol type?

dominicm16:12:34

The discussion above is about JavaScript symbols, you're talking about ClojureScript symbols.