clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
zane 2021-04-26T01:50:44.427300Z

When compiling a namespace that defines a function named binds a variable to eval to JavaScript I get this warning:

WARNING - "eval" cannot be redeclared in strict mode
I would have expected that either --compile-opts '{:output-wrapper true}' or --compile-opts {:rename-prefix "…"} would resolve this, but it doesn’t seem to. Is there another way, or do I have to rename the function variable?

zane 2021-04-26T02:01:15.427600Z

Actually, seems like it’s a let-bound variable named eval that triggers the warning.

sova-soars-the-sora 2021-04-26T03:05:26.428700Z

How can I

{:on-click (fn [e] (gc/toggle node "invisible"))}
specify the node that is being clicked upon?

sova-soars-the-sora 2021-04-26T03:05:51.429100Z

(.. e -target -value) is kinda in the ballpark... not sure if that's the thing

sova-soars-the-sora 2021-04-26T03:06:38.429500Z

I basically want to create a "flip" effect that hides one div and shows another (sibling) div

sova-soars-the-sora 2021-04-26T03:14:22.429600Z

naturally when you overwrite an indigenous function name there will be a warning. do you want the warning to not happen?

sova-soars-the-sora 2021-04-26T03:15:38.429800Z

I would recommend renaming the variable to some other word that isn't a special word, but i'm not an expert.

sova-soars-the-sora 2021-04-26T03:17:19.430300Z

(. e -target) did the trick

sh54 2021-04-26T08:09:26.431Z

I notice that the clojurescript version of hash floors and floating point numbers and then just treats them as ints. This is different to the behavior in clojure which is a little annoying. https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L1012

sh54 2021-04-26T08:09:29.431200Z

So #?(:cljs (is (= (hash 1.2) (hash 1.3)))) yet #?(:clj (is (not= (hash 1.2) (hash 1.3))))

sh54 2021-04-26T08:10:32.431700Z

I get that hashing stuff with floating point numbers in them is probably generally not a great idea but would be nice for my particular case. I am compiling clojure forms to shaders and triggering hot reloads if they change and have been using hash on the new and comparing it to the stored hash of the old to see if things need replacement. Works great unless I try to change a float ever so slightly.

sh54 2021-04-26T08:10:42.431900Z

Any recommendations on how to go about things? It would be nice to use the built in hash. It won’t take that long to write my own special hash but I would prefer to rely on core for this kind of thing.

thheller 2021-04-26T08:13:50.432500Z

don't use the hash to compare stuff 😉

sh54 2021-04-26T08:55:41.435900Z

hehe noted. I wouldn’t normally but its dev tooling so I can tolerate the low collision chance. Doing a full new form to old form = hurts the hot reload speed since right now my relevant def macro does the comparison and so the general shadow-cljs hot reload does not get finished until all those macros get done. It can be a little too slow if the file I edit is required in a bunch of other places.

sh54 2021-04-26T08:58:23.437600Z

I could conceivably push my shader hot reload stuff to a queue and async process that after the shadow-cljs hot reload is done but I’d still like the actual compare to be reasonably performant

thheller 2021-04-26T08:59:14.438100Z

don't know how you are doing stuff but if its a macro you could have that compute something based on the form that you store alongside the output

sh54 2021-04-26T09:00:06.439Z

yeah thats how it is currently done with hash as the function computes what I store alongside the output

sh54 2021-04-26T09:00:49.439800Z

works great unless I want to change a 1.2 to a 1.3. Though that works fine in the clojure version of my project.

thheller 2021-04-26T09:02:20.440200Z

maybe just pr-str the form and md5 it or so. no clue what you are doing exactly 🙂

sh54 2021-04-26T09:04:00.440800Z

oh yeah, good idea. thats a quick alternative.

sh54 2021-04-26T09:28:05.442600Z

(my-md5 (pr-str form)) is quite a bit slower that (hash form) when I just test a bit in the repl. That being said they are both pretty fast in absolute terms so i’ll just have to see how it feels in my workflow.

p-himik 2021-04-26T09:30:28.442700Z

If the forms are compared within the JVM process, comparing the results of pr-str might be faster, because md5 consumes the whole string either way. But then comparing the forms themselves should be even faster, but you say that it's slower.

sh54 2021-04-26T09:33:12.442900Z

I’m looking at some code I wrote a good while ago so I am just relying on some notes I wrote at the time that say that comparing the forms was slow though I will double check now.

sh54 2021-04-26T09:39:48.443100Z

also I checked my macro magic and I am doing the actual compare in the browser. I am only hot reloading my shaders when I am developing so it is unnecessary to compute and store anything during compilation.

sh54 2021-04-26T09:39:49.443300Z

Sorry for the lack of clarity! Trying to explain a little part of of a larger thing without bringing in too many unnecessary details.

p-himik 2021-04-26T09:42:44.443500Z

> I am doing the actual compare in the browser. Can it be done in the JVM process?

p-himik 2021-04-26T09:42:53.443700Z

Without sending anything, I mean.

sh54 2021-04-26T09:46:43.443900Z

potentially. The macro would probably have to do the computes and store to metadata. Then the runtime bit of things would just compare old and new and call the hot reload “hook” if they are different.

sh54 2021-04-26T09:53:36.444100Z

and = is like 300 times slower in my tests in both clj and cljs. I was testing under the assumption that things are most likely equal which I assume is worst case of the = function. And that the old and new form don’t “share” anything between them which I don’t know if is true or not.

sova-soars-the-sora 2021-04-26T14:39:03.445Z

Any tips on how I can make one 2 divs, one default hide, one default show, and click to switch that?

p-himik 2021-04-26T15:01:32.445100Z

Do you use any UI library? If so, it's better to ask in the appropriate channel, e.g. #reagent for Reagent.

sova-soars-the-sora 2021-04-26T15:02:19.445400Z

Thanks. I am using rum. I managed to figure it out! ^_^ keeping a local state and toggling between -1 and 1 via #(* -1 %)

👍 1
Aron 2021-04-26T15:09:48.445700Z

I was about to suggest Element.classList.toggle 🙂

sova-soars-the-sora 2021-04-26T15:13:27.445900Z

I tried to do toggle but i have 2 elements. so rather than toggle them both i have one local atom and if its value is -1 one class is conditionally set, if it's +1 the other class is conditionally set

Aron 2021-04-26T15:16:49.446100Z

obviously doesn't matter in most cases, but changing class attribute on 2 elements is a lighter operation for the browser than adding/removing two elements

Aron 2021-04-26T15:17:55.446300Z

wait, I got confused, you are not removing elements, but I don't quite understand, if you are generating your html, how does that work, what is the mechanism that changes the class? is it's react or something?

yuhan 2021-04-26T16:02:19.446700Z

using +1 and -1 is a bit odd, why not true/false and toggle with not?

yuhan 2021-04-26T16:05:01.446900Z

or even better, name the states something meaningful and toggle between them with a map: eg. (swap! state {:dark :light, :light :dark}), you can do any number of "state transitions" this way

sova-soars-the-sora 2021-04-26T17:03:58.447200Z

it might be good to have multiple states... i don't understand the line (swap! state {:dark :light, :light :dark})

sova-soars-the-sora 2021-04-26T17:05:09.447400Z

@ashnur i'm using Rum

[:div.thang {:class (if (= -1 @visibility-atom) "invisible")
     			:on-click (fn [e] (swap! visibility-atom #(* -1 %)))} 

sova-soars-the-sora 2021-04-26T17:05:58.447600Z

It's like a fake "flip to see the back of this div" but really it's not the back, it's just another div, and i hide one and show one depending on the value of @visibility-atom via the if statement in the :class attribute

sova-soars-the-sora 2021-04-26T17:06:43.447800Z

@qythium maybe you could elaborate on your mini state machine there

sova-soars-the-sora 2021-04-26T17:06:51.448Z

say I want to have 3 modes instead of 2

yuhan 2021-04-26T17:21:31.448200Z

say you have 3 states, using keywords :a :b :c to denote them

(def *state (atom :a)) ;; initial

(def transitions {:a :b, :b :c, :c :a})
This would cycle between all 3 states
(swap! *state transitions)

sova-soars-the-sora 2021-04-26T17:26:46.448500Z

well that's cool and pretty mind-blowing

sova-soars-the-sora 2021-04-26T17:27:05.448700Z

love it

yuhan 2021-04-26T17:28:18.448900Z

Yup, the "maps/sets/keywords as functions" idiom is quite powerful if you get used to it 🙂

sova-soars-the-sora 2021-04-26T17:40:31.449200Z

super cool!

yuhan 2021-04-26T17:43:59.449400Z

note that you might want to guard against invalid states by using #(get transitions % <default>), or using case which throws an error #(case % :a :b, :b :c, :c :a)

sova-soars-the-sora 2021-04-26T17:45:04.449600Z

Ah that is helpful, to have a fall-back...

yuhan 2021-04-26T17:46:31.449800Z

I actually use case most of the time for these things, it's better to catch errors early than have a nil cause damage down the line

sova-soars-the-sora 2021-04-26T17:51:39.450Z

sure. easier to pinpoint the leak

sova-soars-the-sora 2021-04-26T17:54:30.450200Z

clojure is so awesome. that's maybe the simplest code ever for a working state machine.

sova-soars-the-sora 2021-04-26T17:54:57.450400Z

the list of states is also a function for advancing states... brilliant and beautiful

✨ 1
sova-soars-the-sora 2021-04-26T18:14:04.450800Z

thanks for your help everyone, i got a lot done this morning ^.^

brtmr 2021-04-26T18:33:13.454900Z

Hi, I need some help with tooling. I have a web app with a ring-backend in clojure and a reagent frontend in clojurescript. I am using cursive with leiningen. I can run my frontend through figwheel and develop with code-reloading, and I can use the lein ring plugin to run the backend with code reloading. I have found bits and pieces on the figwheel home page / github wiki, but everything either assumes that I am either using deps.edn instead of leiningen is using outdated APIs.

brtmr 2021-04-26T18:34:19.455800Z

Edit: What I am trying to do is run them both in tandem: Backend and Frontend, possibly with code reloading/ a REPL on either side

Aron 2021-04-26T21:01:25.458100Z

fwiw, before shadow-cljs and deps.edn became a thing, I was unable to adopt clojure because both lein and boot were way outside of what I could reach with respect to my time and other constraints. 7 years I knew about clojure but had no way in. I was limited to using cljs packages compiled to js.

sova-soars-the-sora 2021-04-26T21:25:35.458900Z

@mail185 shadow-cljs is great and might be just the ticket https://shadow-cljs.github.io/docs/UsersGuide.html

gorjusborg 2021-04-26T23:28:20.462600Z

how do people do interop w/ js promises in cljs these days? I see promisea, and the <p! macro w/ core.async... but what's idiomatic?