clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
twashing 2021-03-03T02:10:07.152200Z

Does anyone know, when https://clojurescript.org/news/2017-07-12-clojurescript-is-not-an-island-integrating-node-modules, how do we reference packages with @ symbols. In this case @google-cloud/pubsub ? A) Ie how would we include it in a build.edn like this. The example here fails to fetch the module.

{:target       :nodejs
 :output-dir   "public/js/compiled"
 :output-to    "public/js/main.js"
 :install-deps true
 :npm-deps     {:express        "4.17.1"
                :@google-cloud/pubsub "2.1.0"}}
B) And with the right incantation, how would we load it in?
(require '"@google-cloud/pubsub")
(require '"google-cloud/pubsub")
(require '"@pubsub")
(require '"pubsub")

thheller 2021-03-03T08:08:10.154400Z

see https://clojurescript.org/guides/webpack or use shadow-cljs

thheller 2021-03-03T08:08:21.154600Z

the guide you linked is outdated and not recommended today

twashing 2021-03-03T15:46:21.156400Z

Ok, I glanced again at Clojuerscript’s https://clojurescript.org/reference/compiler-options#npm-deps. And it just looks like we need to wrap the @package/name in a string. So that was my initial failure to notice. This works for me.

{:target       :nodejs
 :install-deps true
 :npm-deps     {:express         "4.17.1"
                "@google-cloud/pubsub" "2.1.0"}}

twashing 2021-03-03T02:20:38.152400Z

Ok, so I know the “require” is this: (require '["@google-cloud/pubsub" :as pubsub]) . But still wondering howto get the Clojurescript compiler to pull it in.

Chris McCormick 2021-03-03T07:44:46.154200Z

client: we want a web based solution. also the server has to run behind our firewall. also everything is windows. me: 😎

$ make phoenix-classify-server.exe 
npx shadow-cljs release server app --debug
shadow-cljs - config: /home/chrism/dev/phoenix-species-photo-classifier/shadow-cljs.edn
shadow-cljs - connected to server
[:server] Compiling ...
[:server] Build completed. (81 files, 1 compiled, 0 warnings, 4.21s)
[:app] Compiling ...
[:app] Build completed. (79 files, 0 compiled, 0 warnings, 4.86s)
cp -v public/*.css build/public/
'public/mui.min.css' -> 'build/public/mui.min.css'
'public/style.css' -> 'build/public/style.css'
cp -v public/index.html build/public/
'public/index.html' -> 'build/public/index.html'
npx nexe build/server.js -r "./build/server.js.map" -r "./build/public/**/*" -t win32-x86-12.16.2 -o phoenix-classify-server.exe
ℹ nexe 4.0.0-beta.17
✔ Included 7 file(s)
✔ Already downloaded...
✔ Compiling result
✔ Entry: 'build/server.js' written to: phoenix-classify-server.exe
✔ Finished in 1.175s
anyone else using nexe to ship cljs?

mikejcusack 2021-03-03T15:44:46.156300Z

How do you use Reveal with ClojureScript in Cursive?

mikejcusack 2021-03-03T15:47:18.157Z

For people using Reagent and want to style with Material Design how are you going about it?

mikejcusack 2021-03-03T19:03:43.158700Z

Is there any way to generate ES6+ JS with CLJS?

thheller 2021-03-03T19:06:20.159100Z

which part of ES6? 😛

mikejcusack 2021-03-04T18:47:14.191Z

Thanks for the tip! Man, that's a lot for just +

thheller 2021-03-04T18:57:12.194100Z

+ is just + in most cases in the code. the above is just variadic function dispatch boilerplate since you can't actually use + that way in JS

mikejcusack 2021-03-04T19:02:18.194600Z

Ah, ok

raspasov 2021-03-05T08:10:10.202600Z

@mike.j.cusack and you can do stuff like:

raspasov 2021-03-05T08:10:13.202800Z

(apply + (range 1000))

mikejcusack 2021-03-05T08:54:01.205400Z

Haha, I'm not new to Clojure and ClojureScript. I've just never been a fan of JavaScript so the fact ClojureScript removes that burden has caused me to exist peacefully without opening the hood. I have looked a bit under the hood for Clojure though. I'm not sure why I have a sudden interest in opening the hood now. 😄

raspasov 2021-03-05T09:37:02.205800Z

I can relate to “just never been a fan of JavaScript” 😂

mikejcusack 2021-03-03T19:10:31.159200Z

The useful bits like let and const

thheller 2021-03-03T19:13:45.159400Z

how would that be useful for us? but the answer to that is no, there is no way to make the compiler generate those.

mikejcusack 2021-03-03T19:14:18.159700Z

How is generating old JS with only vars ok in CLJS, but yet if you did that in vanllla JS people would blow your head off?

mikejcusack 2021-03-03T19:14:48.159900Z

I must be missing something

thheller 2021-03-03T19:15:13.160100Z

the compiler takes care of writing JS code that doesn't have those issues

mikejcusack 2021-03-03T19:15:28.160300Z

How?

thheller 2021-03-03T19:16:39.160500Z

how what? any particular thing you are worried about?

mikejcusack 2021-03-03T19:16:56.160700Z

How does the compiler use vars and not have issues?

thheller 2021-03-03T19:17:15.161100Z

the same way you did in "old" JS if you were careful

mikejcusack 2021-03-03T19:17:32.161300Z

?

thheller 2021-03-03T19:18:11.162200Z

what particular thing are you worried about? I really cannot explain the entire compiler over slack 😛

mikejcusack 2021-03-03T19:19:22.163800Z

I'm trying to understand how it can use vars (mutable) and not have issues around the mutability

mikejcusack 2021-03-03T19:19:35.164400Z

But I don't know the compiler under the hood

Lu 2021-03-03T19:19:54.165Z

Just a broad idea ... when you write cljs code and use a variable within a function, the compiler makes sure that generated var won’t be touched by anything else outside of that scope .. so practically it’s treated like a let.

mikejcusack 2021-03-03T19:20:15.165200Z

Ok, and how?

Lu 2021-03-03T19:21:01.166100Z

There’s no how .. the generated code won’t have functions manipulating that var

mikejcusack 2021-03-03T19:21:24.166700Z

I'm saying how does it ensure that

Lu 2021-03-03T19:22:22.167900Z

If you wanted to take the compiled code and change that var I guess you could .. but the code is produced to not ever touch that var

thheller 2021-03-03T19:22:32.168100Z

a) namespacing b) shadowing

thheller 2021-03-03T19:23:30.168300Z

(def a 1) becomes some.ns.a = 1 so it can't clash with (def a 1) in some other ns since that will have a different name

thheller 2021-03-03T19:24:14.168500Z

then if you shadow yourself like (fn [a] (let [a (inc a)] ...) second a will actuall have a different name and not mess with the other one

mikejcusack 2021-03-03T19:27:51.168700Z

And what is stopping some.ns.a from being changed to 2?

thheller 2021-03-03T19:30:31.169Z

nothing

mikejcusack 2021-03-03T19:30:39.169200Z

So how is that ok?

thheller 2021-03-03T19:32:41.169400Z

it is just how CLJ(S) works and just because you can do certain things does not mean that you should. so people in general won't

mikejcusack 2021-03-03T19:33:03.169600Z

So what's stopping rogue code from doing it?

thheller 2021-03-03T19:33:32.169800Z

just like const is pretty much useless in JS. const a = { foo: 1 } can still do a.foo = 2;

mikejcusack 2021-03-03T19:33:51.170Z

That's true and one of my peeves of JS

mikejcusack 2021-03-03T19:33:58.170200Z

But let still does what it claims

lilactown 2021-03-03T19:34:15.170400Z

@mike.j.cusack the semantics of Clojure, which the compiler implements, doesn't allow mutation of vars. So if all your code is in ClojureScript, then the semantics will remain

mikejcusack 2021-03-03T19:35:06.170600Z

Ok. I'm just trying to learn the actual how. I like having a thorough understanding of things.

mikejcusack 2021-03-03T19:35:36.170800Z

I'm trusting that what you guys are saying is true. I just want to know the details to better understand the code

thheller 2021-03-03T19:36:52.171Z

the common problems you can have in JS are not issues you'll have in CLJS. the compiler takes care of the quirks and ensures that the code actually does what you told it to do

lilactown 2021-03-03T19:37:27.171200Z

when the compiler takes your ClojureScript code and converts it to JS, the compiler has rules for how it should write code. It outputs JS code in such a way that it won't cause some of the maintenance issues, like hoisting or mutating things willy-nilly

mikejcusack 2021-03-03T19:37:45.171400Z

Ok...how

lilactown 2021-03-03T19:38:23.171600Z

that's kind of a hard question to answer. It is "a simple matter of programming" as it were

thheller 2021-03-03T19:39:00.171800Z

study the generated code or compiler I guess. that'll give you more answers than we can.

lilactown 2021-03-03T19:39:02.172Z

the compiler has a bunch of different steps that parses your code, analyzes your code, and then turns it into JS according to a set of common rules. those are all implemented in code

mikejcusack 2021-03-03T19:39:24.172300Z

Studying the generated code is really difficult because of how it is all smashed together

thheller 2021-03-03T19:39:47.172500Z

run it through prettier JS or so

lilactown 2021-03-03T19:40:02.172700Z

this can give you a good sense for how CLJS code gets converted to JS, before optimizations are run: http://app.klipse.tech/

lilactown 2021-03-03T19:40:43.172900Z

you can type in CLJS code and see the JS output

mikejcusack 2021-03-03T19:42:05.173100Z

I can't type into the cljs box

lilactown 2021-03-03T19:42:34.173300Z

hmm strange. are you on mobile?

thheller 2021-03-03T19:42:48.173500Z

I also can't see the JS code?

mikejcusack 2021-03-03T19:42:58.173700Z

Nope. And tried with Firefox and Chromium

lilactown 2021-03-03T19:43:38.173900Z

🤷:skin-tone-2: it works on the latest Chrome on my mac for me

lilactown 2021-03-03T19:44:00.174200Z

I'm sure there are other places out there

lilactown 2021-03-03T19:44:09.174400Z

to view this sort of thing

thheller 2021-03-03T19:44:39.174600Z

the code compiles and runs fine but I can't see the JS anywhere

lilactown 2021-03-03T19:45:09.174800Z

hmm. here's what I see

mikejcusack 2021-03-03T19:45:15.175Z

For me the cljs is generated from the clj

mikejcusack 2021-03-03T19:45:36.175200Z

And it's not actually cljs code

thheller 2021-03-03T19:46:03.175400Z

hmm yeah that works but

(fn [a] (let [a (inc a)] (+ a a)))
doesn't

thheller 2021-03-03T19:46:29.175600Z

disregard the CLJ/CLJS symbols. they are kinda confusing. this thing only supports CLJS.

✅ 1
lilactown 2021-03-03T19:47:44.175800Z

@thheller that is weird :thinking_face: it shows JS code once I wrap it with (def foo ,,,)

lilactown 2021-03-03T19:49:41.176100Z

yeah to be clear @mike.j.cusack: the code on the left is the ClojureScript code that one would write, and on the right is the JavaScript code that the compiler outputs

👍 1
thheller 2021-03-03T19:50:05.176300Z

hmm indeed. maybe I should build a thing like this for shadow-cljs 😉

lilactown 2021-03-03T19:50:22.176500Z

that would be neat! 😄

mikejcusack 2021-03-03T19:50:50.176800Z

Ok, now this is helpful, thanks.

mikejcusack 2021-03-03T19:50:56.177Z

Try:

(defn example []
  (let [[count set-count] (js/React.useState 0)]
    [:div#example
     [:p "You clicked " count " amount of times"]
     [:> js/MaterialUI.Button
      {:on-click #(set-count inc)
       :color "primary"
       :variant "contained"}
      "Click"]]))

mikejcusack 2021-03-03T19:51:14.177200Z

So it immediately invokes the functions

mikejcusack 2021-03-03T19:51:17.177400Z

That makes sense

thheller 2021-03-03T19:53:56.177600Z

if you want to get extra confused look at some :advanced optimized output. that is completely mind boggling what the compiler does with that sometimes. 🙂

😁 1