Hello folks! Just to confirm, there are something special that breaks clojurescript hash-map when keys are js/Symbol
?
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
@niwinz symbols don't have good equality semantics in JS, but I suppose if this works for Object
it should work for Symbol
though that should probably be tested first, whether even Object
works
i.e. reference types as keys should work, and that's what Symbol
is
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
sure though why you're using isn't really that important to this problem 🙂
just check the behavior of #js {}
as a key or #js []
, if it works
then Symbol("foo")
should work as well
note if you don't hold onto this somehow you'll never be able to retrieve the value again
i know
js object works as expected
@niwinz feel free to open a JIRA ticket w/ these details
the symbol in js acts as value and not a reference as far as i know
show me?
> Symbol("foo") === Symbol("foo")
> false
in the Node REPL
no sensible equality semantics
then it's not a really a value
yeah this is the real purpose
of symbols
i.e. I wouldn't use this as key myself in CLJS maps
they are different of cljs symbols
if you want all the time the same symbol for "name"
you need to use Symbol.for("name")
ah k which looks like it returns some kind of interned thing
> Symbol.for("a") === Symbol.for("a")
true
yes I just checked
probably this is an easy one? I think we don't have a hashing case for symbols or something like that
this is why i said that symbols are the fastest way to create a unique value
sure but not interested in the detail, just the bug 🙂
hmm i think i don't have access to jira, should I need to write this on http://ask.clojure.org?
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
oh nice!
thanks!
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?
other ideas welcome
wouldn't that break their equality semantics? if Symbol("a")
!= Symbol("a")
the hash can't be based on the string value?
What about putting the guid in a WeakMap keyed by symbol? nm, looks like symbols are not allowed as weakmap keys
that seems like a strange limitation
arguments here: https://github.com/tc39/ecma262/issues/1194
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
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.
did i read correctly that while they can be keys in maps they "are not enumerable in for...in iterations."
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
Different symbol type here, just fyi
what do you mean with different symbol type?
The discussion above is about JavaScript symbols, you're talking about ClojureScript symbols.
ooh right