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?
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.
@timofey.sitnikov shadow-cljs does not support CLJSJS packages, you should use the npm package directly instead.
Will try that.
@nilern, OK that works very well, thank you ...
Using cursive and seeing many unresolved symbols like rn/View, where rn is from (require โreact-nativeโ :as rn)
That would be a question for #cursive, but what you see is expected - Cursive doesn't handle NPM dependencies yet.
To be clear - the code will work just fine. It's just the IDE that doesn't know how to resolve the symbols.
Do you know how to turn that thing off.
Kinda annoying
You can turn all symbol resolution warnings.
FWIW clj-kondo has the convention of not warning for npm libraries which are required with a string name
maybe cursive has the same?
Nope. But I guess you could disable the Cursive warning and leave only the warning from clj-kondo?
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?@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 ๐
@raspasov And yes, sorted map are definitely rare in code bases but for some problems they are a must and become extremely useful
@adam678 I completely agree
I was just speculating why this has stayed hidden for so long
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.
If someone wants to follow this: https://ask.clojure.org/index.php/10377/bug-when-using-nested-sorted-maps
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?
FYI databases can also do this e.g. CREATE TABLE tabe (id text NOT NULL DEFAULT uuid_generate_v4(), ...
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.
@adam678 ^^
Basically, in this particular situation, you just got lucky that Clojure/JVM did not compare the two keys and throw an exception.
Hmm, unless I am misunderstanding the example, which I think I might be. Thinking a bit longer on this ...
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.
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.
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.
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
with a comment about it, even
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
I have to say, that is a pretty subtle difference
Cursive doesnโt have the same, but should have.
I am not an internals expert, but that feels like it should be a bug.
@andy.fingerhut as far as I understand, this is specific to sorted-map, is that right?
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.
So perhaps only PersistentTreeMap
in cljs has this behavior.
which is the type used to implemented sorted-map
, so short answer "yes" ๐
Yes, thatโs what I thought ๐ Hmm
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
)
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.
Yupโฆ
but there are 0 promises you will get lucky like that. You should assume you get unlucky.
I very rarely (and I assume most people also) use sorted-map, so thatโs why this probably hasnโt surfaced earlier
They do have fairly limited use, and they are less time-efficient than regular maps.
Yes, but when you need a sorted map, you really need it ๐
And this issue probably only arises with a sorted-map nested inside another sorted-map, in cljs
Iโve made a good use of them for sorted lists in UIs at some points, for example.
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