clojurescript

ClojureScript, a dialect of Clojure that compiles to JavaScript http://clojurescript.org | Currently at 1.10.879
p-himik 2021-02-05T01:09:29.436600Z

If you receive Hiccup, you can just modify it as a regular data structure before embedding it into a higher order component.

Pete Parker 2021-02-05T03:08:10.440400Z

Has anybody encountered issues passing MetaFn to JS functions? MetaFn isn’t a native JS function, so it isn’t executed as expected. For example:

(js/window.setTimeout #(js/console.log "execute native function")) ;; works
(js/window.setTimeout ^:private #(js/console.log "execute function with metadata")) ;; doesn't execute
I would have expected this to be documented somewhere, or be accounted for in JS interop.

Cj Pangilinan 2021-02-05T03:12:38.442200Z

Hi, I'm getting this error: Caused by: http://java.io.FileNotFoundException: Could not locate cljs/repl/nashorn__init.class or cljs/repl/nashorn.clj on classpath. I'm doing java -cp cljs.jar;src clojure.main repl.clj. It's from the book ClojureScript unraveled. I assume Nashorn is deprecated, but what is the alternative? Thanks.

p-himik 2021-02-05T03:17:40.442300Z

An alternative would be running a NodeJS REPL. I'm using clj and I have this alias in my ~/.clojure/deps.edn:

:cljs-repl {:extra-deps {org.clojure/clojurescript {:mvn/version "RELEASE"}}
                :main-opts ["-m" "cljs.repl.node"]}
which can be used as clj -Mcljs-repl.

p-himik 2021-02-05T03:24:09.442500Z

It's the same for any CLJS type that implements IFn. Keywords, sets, maps, vectors, vars, maybe other things. Interop is finicky in some places, this is one of them.

👍 1
seancorfield 2021-02-05T03:26:26.443900Z

I'm running this command on WSL2 (Ubuntu) on Windows 10 and Google Chrome starts up (on Ubuntu, displayed on Windows 10 via VcXsrv) but I never get the REPL prompt -- suggestions for troubleshooting this?

$ clojure -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "RELEASE"}}}' -M -m cljs.main

seancorfield 2021-02-05T03:27:34.444700Z

The browser shows this URL <http://localhost:9000/?rel=1612464229362> and the expected cljs welcome page, so that part is working...

seancorfield 2021-02-05T03:28:16.445100Z

Chrome Version 88.0.4324.96 (Official Build) (64-bit)

p-himik 2021-02-05T03:29:09.445200Z

Does the network tab show a pending request to localhost (just in case - you should refresh the page after opening dev tools for that tab to have something)?

Cj Pangilinan 2021-02-05T03:39:55.445500Z

Thank you. i'll try the node js repl next. i don't use lein or clj yet. i'm trying to understand how clojurscript works on a low level.

p-himik 2021-02-05T03:44:11.445700Z

clj is just a way to create a classpath for a Java command, it has nothing to do with CLJS. I don't know what cljs.jar contains but you can try running java -cp cljs.jar;src clojure.main -m cljs.repl.node.

seancorfield 2021-02-05T03:45:30.445900Z

Will try that... just a sec...

seancorfield 2021-02-05T03:47:35.446100Z

Yup, looks like the last request just hangs:

{:repl "Thread-620", :type :result, :content "{:status :success, :value \"\"}", :order 2}: 

p-himik 2021-02-05T03:49:22.446300Z

Yeah, it's supposed to be that way - long polling. Hmm, not sure then.

seancorfield 2021-02-05T03:53:08.446500Z

Thanks. This all just works on macOS and I think it's the first time I've tried on WSL2/Windows 10.

p-himik 2021-02-05T03:53:52.446700Z

Just out of interest - does it work without WSL2?

seancorfield 2021-02-05T03:55:20.446900Z

Heh, how am I going to start a REPL without WSL2? I don't have clj installed on Powershell etc.

seancorfield 2021-02-05T03:56:04.447100Z

FWIW, hitting the WSL2 process from Windows via 172.17.159.136 doesn't work either in exactly the same way.

p-himik 2021-02-05T03:56:59.447300Z

clj just creates a classpath - you have said it yourself. :) You can run the Java command manually.

seancorfield 2021-02-05T03:57:50.447500Z

Haha... touche! I don't even have java installed on Powershell.

p-himik 2021-02-05T04:00:47.447700Z

You mean, there's no Java installed anywhere in the system but inside WSL2? Because I'm not sure what Powershell has to do with it - Java is just a regular executable that can be run by any means. In any case, I was just curious, nothing more. Unless someone else can chime in with some ideas, I would try to debug cljs.repl/repl*, namely its need-prompt part. (interestingly, for some reason it uses (identity true) instead of just true, huh)

seancorfield 2021-02-05T04:03:39.448Z

Right, I don't do any dev outside of WSL2 so there are no dev tools installed on the Windows side.

seancorfield 2021-02-05T04:04:06.448200Z

You asked "does it work without WSL2" and there's no way to run Java or Clojure on my machine outside of WSL2.

p-himik 2021-02-05T04:05:50.448400Z

I see. It's just that I used to have Java installed back when I was using Windows not because I did my development there but because something else needed Java. :) "Billions of devices!"

seancorfield 2021-02-05T04:07:03.448600Z

So far nothing has needed Java on Windows 🙂

p-himik 2021-02-05T04:11:27.448800Z

Oh, does the regular clj REPL prompt appear?

seancorfield 2021-02-05T04:35:10.449300Z

Yeah, I do loads of Clojure work on this setup. And I've also had Figwheel Main run fine on this setup.

seancorfield 2021-02-05T04:35:19.449500Z

So it's just the plain cljs REPL.

seancorfield 2021-02-05T04:40:46.449700Z

Yup, just tested Figwheel...

clj -Sdeps "{:deps {com.bhauman/figwheel-main {:mvn/version \"0.2.12\"}}}"  -m figwheel.main
Starts the browser, produces a REPL, all works.

p-himik 2021-02-05T06:18:28.449900Z

Hmm, I'm getting

Failed to launch a browser:
 The BROWSE action is not supported on the current platform!

p-himik 2021-02-05T06:33:48.450100Z

Ah, apparently VirtualBox cannot work with WSL2 at all.

suren 2021-02-05T10:17:13.450800Z

Why does *ns* in clojurescript return nil?

thheller 2021-02-05T10:18:21.451Z

because it doesn't exist in the REPL technically, should only be used in macros

suren 2021-02-05T10:27:03.451500Z

Yup I can confirm it. Thanks

Ivan Fedorov 2021-02-05T11:42:20.454200Z

On Web Workers. Anyone managed to pass CLJS maps between different contexts without serialization? I’ve posted this on reddit for indexation purposes. https://www.reddit.com/r/Clojure/comments/ld5f2h/cljs_web_workers_transferable_db/

Fredrik Andersson 2021-02-05T14:00:04.456200Z

I'm new to clojure/clojurescript and thinking about the possibility to make a macro somehow that builds defines static variables of paths in a map?

Fredrik Andersson 2021-02-05T14:01:02.457300Z

The reason is that i would like to pass paths in state to different functions when rendering my hiccup

Fredrik Andersson 2021-02-05T14:01:37.457900Z

that way i could more easily reuse components of my UI in different parts of my state

Fredrik Andersson 2021-02-05T14:02:19.458700Z

I would like to have them statically defined so that when something changes i get notified by the compiler

Fredrik Andersson 2021-02-05T14:03:57.460200Z

the solution i use now is to

(def state-path-login-username [:login :username])

Fredrik Andersson 2021-02-05T14:05:02.461100Z

but if i have to keep these defines in sync with the model

Fredrik Andersson 2021-02-05T14:05:53.461800Z

is it even possible to write a macro that does this?

p-himik 2021-02-05T14:22:42.461900Z

Do you meant that you want to be able to have something like this in your code

(generate-state-path-defs
  [:login :username]
  [:login :password]
  [:some :other :state])
and end up with
(def state-path-login-username [:login :username])
(def state-path-login-password [:login :password])
(def state-path-some-other-state [:some :other :state])
being actually compiled?

Fredrik Andersson 2021-02-05T14:27:44.462200Z

well thats a start

Fredrik Andersson 2021-02-05T14:28:53.462400Z

but maybe more like this (defstate {:login {:username "" :password ""} :other-state...})

Fredrik Andersson 2021-02-05T14:30:26.462700Z

and end up with something like this

(def state (r/atom {:login {:username "" :password ""} :other-state...}))

(def state-path-login-username [:login :username])

Fredrik Andersson 2021-02-05T14:30:34.462900Z

and so on

p-himik 2021-02-05T14:32:24.463100Z

It is possible. The first step would be to turn the map into a collection of vectors with all possible paths. The second step would be to write macro that generates those def statements and, it seems, a ratom, based on that collection of vectors. The first step is actually a bit harder to implement than the second one and it has nothing to do with macros. If you want to learn more about writing macros to be able to implement the second step yourself, I find this article quite good to get started with them: https://www.braveclojure.com/writing-macros/

p-himik 2021-02-05T14:33:46.463300Z

One thing to note - [:a-b] and [:a :b] will generate the same exact symbol for def in your case. Something to be aware of. Either of the steps could make the check and report any collisions.

p-himik 2021-02-05T14:37:10.463600Z

Another thing - your IDE probably won't be able to figure out that there are some generated def statements. So no autocompletion and symbol resolution unless you customize it yourself.

Fredrik Andersson 2021-02-05T16:02:58.463800Z

ok, thanks ill look into it. But then i know it wouldnt be futile to give it a try

👍 1
2021-02-05T18:15:27.464900Z

👋 , any recs on the best way in 2021 to start on a cljs project where I can’t use JVM at all (target processor has no JDK)?

thheller 2021-02-05T18:16:45.466700Z

you don't need the JVM on the target once everything is compiled

2021-02-05T18:16:45.466800Z

I’m tempted to start from #klipse, and remove pieces I don’t need, rather than work the other way….. my ideal would be a shadow-cljs level of featured REPL, but running on and accessed in the browser rather than from terminal

2021-02-05T18:16:59.467300Z

I need CLJS scripting as a user feature in the webapp

2021-02-05T18:17:17.467900Z

And ideally, it would be homogenous toolchain with how I write the core

2021-02-05T18:18:16.469800Z

Cool, I read through that, I wasn’t sure how relevant it still was in 2021

thheller 2021-02-05T18:18:23.470100Z

hasn't changed

2021-02-05T18:18:48.470700Z

I’ll try to make a clone-able github repo that provides an example of this pattern

2021-02-05T18:19:11.471100Z

oh…. @thheller hahaha, just recognized the name 🙇

👋 1
2021-02-05T18:20:12.472Z

@thheller I got a sense from your blog that this is sort a “yeah, you can do this, but its not a great path yet, avoid if you don’t really really need it”

2021-02-05T18:20:26.472500Z

Does that seem accurate?

thheller 2021-02-05T18:21:17.473300Z

if you need to eval at runtime thats the only path to do it apart from a slightly less powerful eval using https://github.com/borkdude/sci

thheller 2021-02-05T18:22:01.474300Z

and yes, if you don't really need eval then you shouldn't do it as it makes the build rather large

thheller 2021-02-05T18:22:42.474700Z

kinda depends on what kind of eval you are talking about

FlavaDave 2021-02-05T18:39:20.477Z

Having trouble using base64 encoding a file from a file uploader and getting into the body of a request.

(defn form
  []
  [:div 
   [:form {:id       "upload-form"
           :enc-type "multipart/form-data"}
    [:label {:for "upload-file"}
     "upload"]
    [:input {:type   "file"
             :id     "upload-file"
             :name   "upload-file"
             :accept "image/jpeg"}]
    [:button {:on-click #(upload-file "upload-file")}
     "button"]]])

(defn put-file-in-bucket [file path]
  (PUT (str endpoint "/photo/bucket-name/" path)
       {:handler       handler
        :error-handler error-handler
        :body          file}))


(defn upload-file [element-id]
  (let [el        (.getElementById js/document element-id)
        file      (aget (.-files el) 0)
        file-name (.-name file)
        reader    (new js/FileReader)
        binary    (.readAsText reader file)
        b64       (js/btoa binary)]
    (put-file-in-bucket b64 file-name)))
That is as far as ive gotten so far but when i console.log the results of (.readAsText reader file) it comes back as undefined and same as when i use (.readAsBinaryString reader file).

2021-02-05T18:41:35.477900Z

@thheller Hi, build size is no worries for this use, since its cached on-device

borkdude 2021-02-05T18:43:22.478200Z

@snickell you can try sci cljs eval here: https://nextjournal.github.io/clojure-mode/

borkdude 2021-02-05T18:44:25.478500Z

there is a #sci channel if you want to know more

p-himik 2021-02-05T18:45:00.478600Z

Those functions don't return anything. They change the reader in-place.

p-himik 2021-02-05T18:45:55.478800Z

All file operations are async, you cannot directly get a result from something like that - you have to chain the actions together with promises or events.

FlavaDave 2021-02-05T18:48:50.480700Z

ah ok that makes sense

FlavaDave 2021-02-05T18:50:47.483700Z

i found this code online

input.onchange = function () {
  var file = input.files[0],
    reader = new FileReader();

  reader.onloadend = function () {
    // Since it contains the Data URI, we should remove the prefix and keep only Base64 string
    var b64 = reader.result.replace(/^data:.+;base64,/, '');
    console.log(b64); 
  };
the only thing i dont understand is how to use interop on the reader.onLoadEnd = function() …

FlavaDave 2021-02-05T18:51:53.485300Z

would it be (def on-load-end (.onLoadEnd reader #(,,,)?

henrik42 2021-02-05T19:00:15.496900Z

Hey! We have a JavaServerFaces app with some JavaScript code (inlined as well as in js-src). So we're working with post-backs and page-loads/navigation all the time. What could be a migration path to first using CLJS for better UX and later switch to SPA and get rid of JSF? A naive idea would be to just replace the JS with CLJS, but we would be loading it over and over again. May be not too bad since it's an internal app so little latency and much bandwidth and browser cache. Would wrapping the JSF app in an IFRAME help? So load the CLJS just once and keep it while doing the JSF navigation just in the IFRAME. I'm not an expert browser/JS developer so I wonder if that could work. Any thoughts? Anyone else mixing JSF and CLJS?

p-himik 2021-02-05T19:36:12.497300Z

(set! (.-onloadend reader) (fn [event] ...)) This is a decent cheat sheet: https://cljs.info/cheatsheet/

2021-02-05T20:06:48.497700Z

@borkdude so cool!

2021-02-05T20:07:53.498400Z

@borkdude / @thheller What are the eval differences / tradeoffs between the two approaches?

borkdude 2021-02-05T20:11:49.000100Z

if you ask me: self-hosted yields a bigger bundle size (about 8mb unzipped, 1mb zipped) but bundles a full compiler: the code it generates is more performant than an interpreter. sci offers a (significant) subset of clojure as an interpreter: smaller bundle size, but the code in it will not run as performant.

2021-02-05T20:12:24.000600Z

Got it! I’m running on an embedded device without JVM support

2021-02-05T20:12:31.001Z

So bundle size is not a concern

borkdude 2021-02-05T20:12:53.001900Z

sci can run in advanced compiled CLJS and can hook into your advanced compiled functions, which may compensate performance issues

2021-02-05T20:13:01.002200Z

I think….. repl tooling and features, and performance of compiled code are probably my emphasis?

borkdude 2021-02-05T20:13:10.002600Z

whereas self-hosted cannot run in advanced mode

2021-02-05T20:13:25.002900Z

oh interesting!

borkdude 2021-02-05T20:18:59.003600Z

@snickellto go back to your original problem: > to start on a cljs project where I can’t use JVM at all (target processor has no JDK) why don't you compile on another machine which does have a JVM and then move the JS to the device that doesn't have a JVM?

borkdude 2021-02-05T20:19:24.003900Z

I mean, browsers don't have a JVM either (well, let's ignore applets). That's no reason to not use CLJS + JVM for dev

2021-02-05T20:22:50.004800Z

I need to compile potentially complex user entered scripts

2021-02-05T20:23:04.005200Z

(or interpret)

borkdude 2021-02-05T20:23:08.005300Z

right, gotcha. yeah, then self-hosted or sci makes sense.

2021-02-05T20:23:28.005800Z

thanks, I appreciate your feedback, you always know least when you start on a new area

2021-02-05T20:23:42.006200Z

You’re helping me not blow my foot off while I figure out the self-hosted area

FlavaDave 2021-02-05T20:24:29.006300Z

Thank you. I’ll try that out later today

Ricardo Cabral 2021-02-05T21:49:09.009600Z

Hello all, why is so complicated to add npm dependencies to a clojurescript project? Do people use shadow-cljs for it? I am just trying to add react and testing libraries (https://testing-library.com/) along with react. and figwheel and clojurescript. Can someone let me know what is the stack to create a project TDD based with clojurescript?

seancorfield 2021-02-05T23:24:01.011900Z

@ricardozcabral I suspect a lot of folks doing ClojureScript just use clojure.test because it's built in and then use one of the various cljs test runners (I use the CLI/`deps.edn` rather than lein so I use Olical's cljs-test-runner for some stuff and I just started using Figwheel Main and I seem to recall that automatically runs your tests for you and can display them in a browser).

👍 1
seancorfield 2021-02-05T23:24:53.012300Z

(and, so far, I've managed to avoid npm and any dependencies from that!)

borkdude 2021-02-05T23:26:18.012500Z

https://github.com/Olical/cljs-test-runner I like this one

👍 1