Fork me on GitHub
#clojurescript
<
2023-06-23
>
Somi Cho07:06:39

What's the recommended way of doing CSS in CLJS projects these days?

p-himik08:06:23

There's no "recommended" way, you choose what best fits your needs and preferences. In one project I use what MUI offers because the whole UI is written in MUI. In another project I use SCSS.

👍 2
isak14:06:05

> what is here now will very likely stay as it is forever. Sounds nice because tailwind is annoying to keep up with.

M19:06:13

Ha +1 against tailwind. I like https://github.com/roosta/herb

reefersleep11:06:34

Is there a way to ensure that sort respects locale globally when handling strings in my Clojurescript application? Maybe there's some way to hook into the sorting? I looked at the source for sort, and it's not obvious to me. Maybe not possible. This is what I have:

(-> ["så" "sæ" "sa" "sø"]
    sort)
;;=> ("sa" "så" "sæ" "sø")
This is what I want:
(-> ["så" "sæ" "sa" "sø"]
    sort)
;;=> ("sa" "sæ" "sø" "så" )

p-himik11:06:06

How would you do the same in JS?

p-himik11:06:57

The only way to hook into sort is by providing a custom comparator.

reefersleep11:06:05

I know that there are some protocols that you can extend in Clojurescript, I thought there might be something similar in this regard - like an override of sorts.

reefersleep11:06:23

We do a lot of sorting (I guess most frontends do), and I just want to make it as easy (yes, easy, not simple) as possible to do it correctly in every case. Relying on programmers to remember to provide a comparator in every case is bound to fail at some point 🙂

reefersleep11:06:48

And the thing is, it's subtle, so you probably won't notice right away.

p-himik11:06:16

Nah, just comparators. I'd create a common function in some util namespace that wraps sort with the desired comparator. For my own education - why is the order that you want is, as you say, correct? Why is the default behavior incorrect?

reefersleep11:06:00

That's how the Danish letters go, alphabetically 🙂

A B C D E F G H I J K L M N O P Q R S T U V X Y Z Æ Ø Å

reefersleep12:06:16

I'll probably end up doing what you suggest. It was what I thought of as the only obvious viable solution. Thank you for lending me your encyclopaedic knowledge, @U2FRKM4TW

p-himik12:06:44

Oh, so it's locale-dependent and not something that's universally correct, gotcha.

'Æ'.localeCompare('Å', 'en')
=> 1
'Æ'.localeCompare('Å', 'da')
=> -1
And yeah, I'd use that localeCompare in that custom comparator then, if both arguments are strings. Note that you'll have hard time comparing things like vectors of vectors of strings - every level of nesting you will have to handle manually since the comparator is applied only at the top level.

reefersleep12:06:48

Mostly it'll be direct comparison of strings. But I assume that if I were to implement a sort function that wraps sort and uses a comparator, I can just check to see if I'm comparing strings or other things, and either use sort or sort localecompare-compator? Maybe it's more involved than that, but at least I have the sort code as inspiration.

reefersleep12:06:41

oh wait, I get what you're saying.

reefersleep12:06:25

Since it's sort all the way down, if I e.g. sort vectors of strings, I can't tell my function to recursively use comparators without writing some really hairy code.

reefersleep12:06:56

Another argument for overriding sort globally 🙂 If only I could.

reefersleep12:06:56

Scratch that, I'm talking out of a sleep-deprived brain. I get what you're saying. Comparator on root level. Sorting root-level stuff that contains strings further down the data structure does not employ the comparator further down. Gotcha.

reefersleep12:06:13

I think I'll write a sort-danish-strings fn with a localeCompare comparator, note in the docstring that it can only be used for sorting strings and not things that contain strings, and call it a day.

👍 2
p-himik12:06:15

You'll probably never need to sort arbitrarily nested data in a locale-aware way. And if you do end up need to sort collections, you can always create the right comparator on the spot that will know the shape of the data.

👌 2
reefersleep12:06:51

I'm sure you're right about that 🙂 Can't come up with a single case where I'd needed it.

indy17:06:03

I have some vars in cljc that have metadata, can I reliably use the metadata in cljs? Will they be resolved correctly at build time? (the metadata for the vars are not going to change at runtime)

p-himik17:06:44

Yes. So e.g. if you have (def ^:a x 1) then (js/console.log (:a (meta #'x))) will be printing out true. Even after a release build.

indy17:06:02

Thanks. I’m looking to dynamically find the var and get it’s name in cljs. I guess that’s not possible? Might it be possible with macros?

(defn sym
  [v]
  (let [{:keys [ns name]} (meta (var v))]
    (symbol ns name)))

p-himik17:06:32

What do you mean by "dynamically"? var is not a function, it's a special form - in the example above it will try to find a var called v and not as whatever is in the v.

p-himik17:06:37

In CLJ there's resolve for it, but it doesn't exist for CLJS. IIRC, you have to ask CLJS analyzer in a macro to get what you need from a CLJS var. Unless that var is in a CLJC file and has the same metadata on all platforms.

indy17:06:37

Right, thanks for the direction!

indy19:06:20

I was able to get what I want with these two macros I wrote in clj that I import in cljs:

(defmacro var-meta
  [sym]
  `(meta (var ~sym)))

(defmacro var-sym
  [sym]
  `(let [m# (var-meta ~sym)]
     (symbol (str (:ns m#)) (str (:name m#)))))