clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
Timofey Sitnikov 2021-03-25T10:45:17.264Z

Good morning Clojurians, I am trying to use cljsjs.material-ui using Clojure CLI (deps.edn) where I specify the material UI as one of the deps like so: cljsjs/material-ui {:mvn/version "4.11.0-0"}. When I require it, like so: [cljsjs.material-ui] and try watch the app using shadow-cljs, I get this error: The required namespace "cljsjs.material-ui" is not available, it was required by "app/ui/root.cljs". Is it possible to include this package using Clojure CLI?

nilern 2021-03-25T10:53:32.264100Z

You could also use npm or yarn instead of cljsjs if you are using shadow, but I don't know if that would solve this.

โ˜๏ธ 1
thheller 2021-03-25T11:00:07.264700Z

@timofey.sitnikov shadow-cljs does not support CLJSJS packages, you should use the npm package directly instead.

1
Timofey Sitnikov 2021-03-25T11:03:27.264900Z

Will try that.

Timofey Sitnikov 2021-03-25T11:51:03.265100Z

@nilern, OK that works very well, thank you ...

2021-03-25T15:28:35.266900Z

Using cursive and seeing many unresolved symbols like rn/View, where rn is from (require โ€œreact-nativeโ€ :as rn)

p-himik 2021-03-25T15:30:50.267Z

That would be a question for #cursive, but what you see is expected - Cursive doesn't handle NPM dependencies yet.

p-himik 2021-03-25T15:31:18.267200Z

To be clear - the code will work just fine. It's just the IDE that doesn't know how to resolve the symbols.

2021-03-25T15:32:16.267400Z

Do you know how to turn that thing off.

2021-03-25T15:32:18.267600Z

Kinda annoying

p-himik 2021-03-25T15:34:05.267800Z

You can turn all symbol resolution warnings.

borkdude 2021-03-25T16:06:48.268100Z

FWIW clj-kondo has the convention of not warning for npm libraries which are required with a string name

borkdude 2021-03-25T16:06:52.268300Z

maybe cursive has the same?

p-himik 2021-03-25T16:08:27.268500Z

Nope. But I guess you could disable the Cursive warning and leave only the warning from clj-kondo?

Helins 2021-03-25T17:01:36.273100Z

After hours of fighting, I believe I have actually uncovered a bug in CLJS. This misbehaves weirdly while in Clojure, it does not:

(def tree
     (sorted-map 3
                 (sorted-map 1
                             {:a 'leaf-A})))

(def subtree
     (sorted-map 1
                 (sorted-map 100
                             {:b 'leaf-B})))

;; Fine, of course, but now...

(assoc tree
       3
       subtree)

;; Throws:   Error: Cannot compare :a to 100
In Clojure JVM, the subtree gets assoc'ed as expected and that's it. In CLJS, given the error, it looks like it is doing some kind of merge... But why?! That part of the original tree should not be considered at all, should it?

๐Ÿ™Œ 1
Helins 2021-03-26T08:23:58.283800Z

@andy.fingerhut Thanks for the detailed answers, you are probably onto something with identical? vs = Still feels like a bug however, doesn't it? That :a keyword in our examples should not have anything to do with the new tree. Logically speaking, Clojure's implementation is intuitive and CLJS's one is not, in my opinion. I'll post this on http://ask.clojure.org ๐Ÿ˜‰

Helins 2021-03-26T08:24:49.284Z

@raspasov And yes, sorted map are definitely rare in code bases but for some problems they are a must and become extremely useful

raspasov 2021-03-26T08:32:24.284200Z

@adam678 I completely agree

raspasov 2021-03-26T08:32:58.284400Z

I was just speculating why this has stayed hidden for so long

Helins 2021-03-26T08:37:20.284600Z

I discovered this while working on: https://github.com/helins/rktree.cljc It must be one of the very few existing examples where nested sorted maps are used systematically. Even then, it took me a while and escaped tests. This error happens only in that specific scenario. Other forms of nested sorted maps and various updates are just fine.

Helins 2021-03-26T08:49:58.284900Z

If someone wants to follow this: https://ask.clojure.org/index.php/10377/bug-when-using-nested-sorted-maps

๐Ÿ‘ 1
Ronny Li 2021-03-25T17:41:35.274900Z

Hi everyone, how reliable is https://github.com/lbradstreet/cljs-uuid-utils/blob/master/src/cljs_uuid_utils/core.cljs#L60-L78 for creating globally unique identifiers? Can I use it to create unique IDs in my database?

nilern 2021-03-26T10:40:56.293900Z

FYI databases can also do this e.g. CREATE TABLE tabe (id text NOT NULL DEFAULT uuid_generate_v4(), ...

๐Ÿ™ 1
2021-03-25T20:16:59.275600Z

Unless you look under the hood at a particular tree shape for a sorted-map, you have no way to know which keys will be compared to each other via the comparator function, and which will not. It is only going to give predictable behavior if all of the keys in a sorted map can be compared to each other without throwing exceptions.

2021-03-25T20:17:02.275800Z

@adam678 ^^

2021-03-25T20:17:36.276Z

Basically, in this particular situation, you just got lucky that Clojure/JVM did not compare the two keys and throw an exception.

2021-03-25T20:18:38.276200Z

Hmm, unless I am misunderstanding the example, which I think I might be. Thinking a bit longer on this ...

2021-03-25T20:31:08.276400Z

I think the difference between Clojure and ClojureScript in this case is because Clojure when doing assoc, checks for an already-existing key whether the current val is identical? to the new val, which is always a fast check that can never throw an exception, and if (identical? old-val new-val) returns true, the assoc implementation optimizes by returning the current collection, not a new one.

2021-03-25T20:31:33.276600Z

ClojureScript instead does = on the new and old value, which is a deep comparison if they are not identical objects in memory, which leads to the exception you are seeing.

2021-03-25T20:32:20.276800Z

I don't know whether cljs maintainers would consider this a bug or not, but at least that is the root cause of the different behavior here.

2021-03-25T20:33:19.277Z

Here is the relevant line of the Clojure implementation doing Java identity comparison: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentTreeMap.java#L132

2021-03-25T20:33:24.277300Z

with a comment about it, even

2021-03-25T20:34:32.277600Z

Here is the corresponding line in cljs implementation that uses cljs = instead: https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L8857

2021-03-25T20:35:11.277900Z

I have to say, that is a pretty subtle difference

cfleming 2021-03-25T20:44:25.278400Z

Cursive doesnโ€™t have the same, but should have.

๐Ÿ™ 1
raspasov 2021-03-25T20:54:14.278600Z

I am not an internals expert, but that feels like it should be a bug.

๐Ÿ‘ 1
raspasov 2021-03-25T21:00:58.278800Z

@andy.fingerhut as far as I understand, this is specific to sorted-map, is that right?

2021-03-25T21:04:23.279Z

It looks like cljs PersistentHashMap uses identical? rather than = in this case, as far as a quick check of the code by me can tell.

2021-03-25T21:04:40.279200Z

So perhaps only PersistentTreeMap in cljs has this behavior.

2021-03-25T21:05:05.279400Z

which is the type used to implemented sorted-map, so short answer "yes" ๐Ÿ™‚

raspasov 2021-03-25T21:05:57.279600Z

Yes, thatโ€™s what I thought ๐Ÿ™‚ Hmm

raspasov 2021-03-25T21:09:14.279800Z

It is a pretty trippy difference, and it only shows up in certain cases:

(comment

  (def tree
    (sorted-map 3
                (sorted-map 1
                            {:a 'leaf-A})))
  (def subtree
    (sorted-map 1
                (sorted-map 100
                            {:b 'leaf-B})))


  (assoc tree 3 (into {} [[1 (sorted-map 42 nil)]]))
  ;=> {3 {1 {42 nil}}}

  (assoc tree 3 (into (sorted-map) [[1 (sorted-map 42 nil)]]))
  ;=> Error: Cannot compare :a to 42

  )

๐Ÿ‘ 1
2021-03-25T21:10:45.280Z

Sometimes you get lucky and a sorted-map comparison doesn't compare bad pairs of keys with each other, depending upon the tree structure, as I mentioned above.

raspasov 2021-03-25T21:10:54.280200Z

Yupโ€ฆ

2021-03-25T21:11:12.280400Z

but there are 0 promises you will get lucky like that. You should assume you get unlucky.

raspasov 2021-03-25T21:11:14.280600Z

I very rarely (and I assume most people also) use sorted-map, so thatโ€™s why this probably hasnโ€™t surfaced earlier

2021-03-25T21:11:36.280900Z

They do have fairly limited use, and they are less time-efficient than regular maps.

raspasov 2021-03-25T21:12:07.281100Z

Yes, but when you need a sorted map, you really need it ๐Ÿ™‚

2021-03-25T21:12:09.281400Z

And this issue probably only arises with a sorted-map nested inside another sorted-map, in cljs

raspasov 2021-03-25T21:13:09.281700Z

Iโ€™ve made a good use of them for sorted lists in UIs at some points, for example.

2021-03-25T21:14:57.281900Z

If someone wants to file a question at http://ask.clojure.org asking whether this is considered a bug or not, feel free to include any or all of the details above pointing at the code implementation difference, which would help whoever might change the cljs behavior

๐Ÿ‘ 2