cljs-dev

ClojureScript compiler & std lib dev, https://clojurescript.org/community/dev
niwinz 2020-12-22T13:16:08.090500Z

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

niwinz 2020-12-22T13:16:25.090900Z

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

dnolen 2020-12-22T13:49:02.092400Z

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

dnolen 2020-12-22T13:49:21.093100Z

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

dnolen 2020-12-22T13:49:47.094Z

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

niwinz 2020-12-22T13:49:53.094200Z

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

dnolen 2020-12-22T13:50:16.094900Z

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

dnolen 2020-12-22T13:50:32.095700Z

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

dnolen 2020-12-22T13:50:53.096200Z

then Symbol("foo") should work as well

dnolen 2020-12-22T13:52:23.097200Z

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

niwinz 2020-12-22T13:52:31.097800Z

i know

niwinz 2020-12-22T13:52:50.098200Z

js object works as expected

dnolen 2020-12-22T13:53:31.099200Z

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

niwinz 2020-12-22T13:53:31.099400Z

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

dnolen 2020-12-22T13:53:44.099600Z

show me?

dnolen 2020-12-22T13:54:08.099900Z

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

dnolen 2020-12-22T13:54:11.100100Z

in the Node REPL

dnolen 2020-12-22T13:54:25.100500Z

no sensible equality semantics

dnolen 2020-12-22T13:54:28.100700Z

then it's not a really a value

niwinz 2020-12-22T13:54:53.101200Z

yeah this is the real purpose

niwinz 2020-12-22T13:54:56.101400Z

of symbols

dnolen 2020-12-22T13:55:00.101800Z

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

niwinz 2020-12-22T13:55:17.102400Z

they are different of cljs symbols

niwinz 2020-12-22T13:55:26.102900Z

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

niwinz 2020-12-22T13:55:37.103400Z

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

dnolen 2020-12-22T13:56:33.104100Z

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

niwinz 2020-12-22T13:56:34.104300Z

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

dnolen 2020-12-22T13:56:43.104500Z

yes I just checked

dnolen 2020-12-22T13:56:58.105200Z

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

niwinz 2020-12-22T13:57:06.105400Z

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

dnolen 2020-12-22T13:57:24.105800Z

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

niwinz 2020-12-22T13:57:53.106300Z

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

niwinz 2020-12-22T14:00:48.107300Z

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

dnolen 2020-12-22T14:00:49.107500Z

https://clojure.atlassian.net/browse/CLJS-3290

niwinz 2020-12-22T14:01:03.107700Z

oh nice!

niwinz 2020-12-22T14:01:07.107900Z

thanks!

dnolen 2020-12-22T14:16:37.109300Z

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?

dnolen 2020-12-22T14:16:39.109500Z

other ideas welcome

dpsutton 2020-12-22T14:59:00.110500Z

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

favila 2020-12-22T15:06:11.112Z

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

favila 2020-12-22T15:08:13.112700Z

that seems like a strange limitation

favila 2020-12-22T15:09:33.112900Z

arguments here: https://github.com/tc39/ecma262/issues/1194

borkdude 2020-12-22T15:09:51.113500Z

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

favila 2020-12-22T15:14:37.113600Z

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.

dpsutton 2020-12-22T15:17:02.113800Z

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

favila 2020-12-22T15:22:30.114Z

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

dominicm 2020-12-22T16:15:14.114200Z

Different symbol type here, just fyi

borkdude 2020-12-22T16:27:37.114400Z

what do you mean with different symbol type?

dominicm 2020-12-22T16:28:34.114600Z

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

borkdude 2020-12-22T16:29:16.114800Z

ooh right