Fork me on GitHub

Maybe some people here?


There is also #aws-lambda channel

👍 4
Ivan Koz12:01:38

i'm a noob can somebody answer if we plan CLJS on WebAssembly?


no plans. at least until wasm gets support for GC and probably other things.

Ivan Koz12:01:03

whats are other things

Ivan Koz12:01:21

what do we miss in wasm to make clj runtime


don't know. I don't care much at this point. no official work is being done AFAIK.

Ivan Koz12:01:46

alright thank you Thomas, if anyone has more info on missing pieces in wasm, please tag me


Curious, how would you say the clojurescript scene has changed in the last ~2 years? In terms of dominant libraries, techniques etc

Roman Liutikov15:01:15

hmmm, I’d say nothing changed, majority is still using Reagent and re-frame

👀 4

There is also which should be a lot more appealing than it was 2 years ago, particularly if you want to build full stack applications with a Datomic back end.

👀 4

What about React hooks? How good of a decision is it (not) to use them? Particularly when they're all the rage in the wider js world


:thumbsup: I re-read it now. Was aware of it; I'm just not sure if people are using it to build apps, how it compares in practice to a re-frame experience, etc


I recall some discussions about how hooks and some of the other recent react features essentially replicate already existing functionality from reagent. The only one I could find again was, which kind of sums up those conversations as I remember them.


interesting thread, thanks!

Filipe Silva16:01:13

heya, are there any breaking changes one should be aware of when updating to 1.10.59 and using cljs.spec.alpha? I'm updating a project's cljs 1.10.520 to `1.10.597` , and my optimised build now fails when loading something spec related

| TypeError: Cannot read property 'prototype' of ...
$APP.$cljs$spec$alpha$t_cljs$0spec$0alpha62946$$.prototype.$cljs$spec$alpha$Spec$gen_STAR_$arity$4$ = $JSCompiler_unstubMethod$$(6, function($_$jscomp$256$$, $overrides$jscomp$11$$, $path$jscomp$62$$, $rmap$jscomp$11$$) {
  return $APP.$cljs$core$truth_$$(this.$gfn$) ? this.$gfn$.$cljs$core$IFn$_invoke$arity$0$ ? this.$gfn$.$cljs$core$IFn$_invoke$arity$0$() : this.$gfn$.call(null) : $APP.$cljs$spec$alpha$re_gen$$(this.$re$, $overrides$jscomp$11$$, $path$jscomp$62$$, $rmap$jscomp$11$$, $APP.$cljs$spec$alpha$op_describe$$(this.$re$));
(alexmiller was kind enough to direct me here instead of #clojure-spec since cljs.spec.alpha has a different imp than spec.alpha)


did you identify the bit of code responsible for this?

Filipe Silva16:01:55

stepping through the exceptions showed this particular bit as being the one that yielded the final exceptions

Filipe Silva16:01:15

I haven't traced these symbols to see where they are used yet


no I mean the actual source code that lead to this code


likely something including (when gfn (gfn)) and reify

Filipe Silva16:01:03

I think we mean the same thing, insofar as I have to go figure out how these symbols trace back to my source

Filipe Silva16:01:50

I haven't done that yet but it's next on the docket, now that I know there isn't something obvious I should be following to update


also search the source for other references to $cljs$spec$alpha$t_cljs$0spec$0alpha62946$$


other modules or so, just to see if it was maybe moved elsewhere

Filipe Silva17:01:40

will do, thank you for the hint

Filipe Silva23:01:40

I was working on this a bit more today

Filipe Silva23:01:08

I did identify the bit of code that does it by using sourcemaps

Filipe Silva23:01:23

it seems related to reify, but it's in the source for cljs.spec


yes, that was expected


$cljs$spec$alpha$t_cljs$0spec$0alpha62946$$ its in the name 😉


thats pseudo name for a reify in cljs.spec.alpha


would help to know which one

Filipe Silva23:01:01

I think regex-spec-impl, let me double check

Filipe Silva23:01:29

I've been doing release builds all day and trying variations of things to see if I could narrow it down... must have done some 40 at least


what do you get when you look for $cljs$spec$alpha$t_cljs$0spec$0alpha62946$$ in your output?


(note that changes between each compile since its a gensym)

Filipe Silva23:01:13

one second, let me just give you the findings I already have

Filipe Silva23:01:22

I think I've finally hit a way to make it not happen

Filipe Silva23:01:15

• will not error if there are only s/def • will error if there are s/assert or s/fdef • doesn't matter if s/check-asserts was used, or what the value was • only takes a simple assert to fail e.g. (s/def ::str string?)(s/assert ::str "abc") • will error if the assert is in a lazy module • will not error if the assert is in the initial non-lazy module • once there is an assert in the initial non-lazy module, having asserts in the non-lazy modules doesn't seem to cause errors

Filipe Silva23:01:28

that last bit was what I just figured out

Filipe Silva23:01:05

will uncomment all the other asserts to see if it still holds true outside the sample code I was using


so I should be able to reproduce that


hmm dunno how to reproduce ... seems to be working fine


frankly the code in spec scares me ... the macro driven nature makes it extremely hard to follow


and the code it generates is crap


ah no I got it reproduced

Filipe Silva00:01:57

what was missing?

Filipe Silva00:01:27

I managed to get into a bad state again, I think after I uncommented fdefs....

Filipe Silva00:01:40

I'm guessing both assert and fdef need to be in the entry module

Filipe Silva00:01:24

can verify it doesn't even need the s/def, (s/assert string? "abc") is enough


ok the problem seems to be that the closure compiler recognizes the "class" created by reify


but due to cross module motion moves parts of it to the other module


since it doesn't know that the "class" is constructed conditionally


or rather when first calling the fn


interesting ...

Filipe Silva00:01:27

in the codebase I am on, adding this to the entry module makes everything else work ok

(s/assert boolean? true)
(s/fdef boolean? :ret boolean?)


yes, because that prevents the cross-module-motion

Filipe Silva00:01:01

yeah I imagined it'd pull it to the entry

Filipe Silva00:01:16

I'll make an issue


didn't you say :output-wrapper made it work?

Filipe Silva00:01:56

no, output-wrapper made that random weird npm lib work ok


I'm pretty certain this is a bug in CLJS and I'm pretty sure its one they won't fix

Filipe Silva00:01:12

it's pretty easy to work around, just very surprising


I'm surprised this doesn't happen more often


now that I see it its a pretty obvious flaw in reify

Filipe Silva00:01:51

so you can imagine a repro without spec?


well ... I knew about the issue in other contexts. that it affects method motion is news to me 😛


yes. it isn't related to spec at all

Filipe Silva00:01:55

I don't think I understand reify well enough to repro with it

Filipe Silva00:01:10

does the cljs issue tracker issue accept shadow-cljs repros?


the hard part is getting the closure compiler to move the code in a similar way


that I also can't do


no they don't


I think I can repro this without shadow-cljs


don't need the async loader at all

Filipe Silva00:01:32

if it helps, this project has a bunch of lazy modules, not just one


I have it reproduced with 10 lines of code or so


just need to figure out how to configure cljs.main. never really use that.


(ns test.main
    [cljs.spec.alpha :as s]))

(s/def ::foo pos-int?)

(defn init []
  (js/console.log "test.main init"))


(ns test.mod-a
    [cljs.spec.alpha :as s]
    [test.main :as main]))

(defn init []
  (js/console.log "mod-a init")
  (s/assert ::main/foo -1))


;; shadow-cljs configuration


 {9300 "public"}

  {:target :browser
   {:shared {:entries []}
    :main {:init-fn test.main/init
           :depends-on #{:shared}}
    :mod-a {:init-fn test.mod-a/init
            :depends-on #{:shared :main}}}}}}


<script src="js/shared.js"></script>
<script src="js/main.js"></script>
<script src="js/mod-a.js"></script>




don't really need the "shared" module but CLJS has the implicit cljs_base module so need 3 for testing


if you feel like reproducing with just cljs.main and reporting the CLJS Jira go ahead


way too late for me to try that

Filipe Silva00:01:12

I'm wrecked from looking for this all afternoon, but I think I'll try to repro and report tomorrow morning, or afternoon

Filipe Silva00:01:34

haven't used cljs main either, and that sort of thing is usually a bit hard on windows

Filipe Silva00:01:48

but it might work out with wsl

Filipe Silva00:01:53

thanks for all the help figuring this out


you did all the hard work 😛

Filipe Silva00:01:15

well hard work isn't always enough


ok ... I reproduced it with pure CLJS ... can't sleep anyways when thinking about this

Filipe Silva01:01:18

this sounds like a tough one to fix

Filipe Silva01:01:23

nice minimal code too

Filipe Silva01:01:52

can you link the issue here if you're opening it?


would be great if you open the issue. I don't really have the bandwidth to pursue this further.

Filipe Silva10:01:58

feel free to edit any innacuracies

Filipe Silva10:01:14

will ping David about it as well

Filipe Silva10:01:46

@dnolen in regards to the spec regression on 1.10 that I mentioned a couple of days ago, @thheller looked into it with me and we found it's related to reify across modules. Opened issue for it:

👍 4

@filipematossilva not aware of anything - there were some fixes in the last release but nobody else reported a regression yet - just other bugs / missing things

Filipe Silva16:01:05

coolio, thank you for the info

Filipe Silva16:01:21

I'll try to narrow it down and see if it's something silly we're doing or if there's some regression


@filipematossilva thanks please file a ticket if you can isolate a regression

Alex Miller (Clojure team)20:01:26

Have you filled out the 2020 State of Clojure Community Survey yet? It's a great source of info in understanding the community, and we'd welcome your participation if you have a few minutes.

❤️ 4

Is ISeq implemented for JS objects, arrays, and ES6 sets? I’m wondering if it would be possible to keep immutability through functions rather than the data structures being immutable themselves. The question mainly comes from concern about performance in certain situations like creative coding and interactive graphics. I was told that CLJS’s immutable data structures can be too slow in these cases which led me to wonder if we could just implement the ISeq functions for JS data structures purely


This of course wouldn’t defend again third-party code from mutating them, but it would be a step.

Roman Liutikov20:01:29

I think iteration is about 2-3x slower in general, so it really depends on what is slow for you.

Roman Liutikov20:01:43

Also take a look at cljs-bean

👀 4

all cljs data structures are necessarily javascript data structures underneath. and cljs already has an answer to "discard immutability for speed" (transients) that my guess is is pretty well tuned


what I'm saying is if you find some big wins see if you can get it back into the cljs transients code 🙂


Again, this is just an area I’m interested coding with CLJS in but have been warned against it for performance reasons, including with the use of transients


But I don’t have personal experience with this problem yet, nor do I know if said others know about cljs-bean


cljs-bean looks promising


It is definitely easier for some kinds of code to squeeze out the best performance of the language you can if you use mutable data structures. I do not know for sure, but it might be impossible (or at least highly impractical) to achieve maximum performance in some applications using only immutable data structures. That said, you can often achieve good enough performance using immutable data, when you aren't writing a game engine or the inner loop of some heavy number crunching code.


If you are working on code that takes 90% or more of the time and trying to optimize it, then I'm not sure JS is even the right language.


I’ve also considered creative coding in Rust 🙂 Cause I don’t want to learn C++


IMO with enough care you can always write cljs code which will transpile into no-overhead js similar to hand-written js (e.g. using a lot of interop and native js arrays and objects) - it just won’t be idiomatic clojure code so I’m pretty confident in using cljs in all scenarios where js would be used, I keep using cljs in idiomatic way and later when I identify performance issues, I rewrite hot paths into non-idiomatic fast cljs or in the worst case I have always escape hatch to rewrite such hot code in js directly and use it from rest of my cljs codebase

👍 8

Sure, makes sense


It is difficult for us to know how nuanced and thoughtful the suggestion to avoid immutable data was 🙂


yeah using native js arrays seems like a good trick when you need it

cljs.user=> (simple-benchmark [arr #js [1 2 3 4 5 6 7 8]] (areduce arr i ret 0 (+ ret (aget arr i))) 500000000)
[arr #object[cljs.tagged-literals.JSValue]], (areduce arr i ret 0 (+ ret (aget arr i))), 500000000 runs, 3530 msecs
cljs.user=> (simple-benchmark [arr [1 2 3 4 5 6 7 8]] (reduce + 0 arr) 500000000)
[arr [1 2 3 4 5 6 7 8]], (reduce + 0 arr), 500000000 runs, 38302 msecs


I have met some developers who worry about performance when it isn't crucial.


where I see a problem is when my idiomatic cljs code needs to interact heavily with rest of js, that needs marshalling between js native data structures and cljs data structures - it is annoying/error prone and could lead to performance issues


@mruzekw note nothing is stopping you from writing ClojureScript around JS native types


that's how ClojureScript itself is implemented


But can I use, say, cljs map, filter, reduce with them?


Or would it be (.map js-arr …)


with arrays you can use those yes


Whoops haha, js-arr


transducers perform reasonably well on arrays - in striking distance of handwritten loops (because effectively that's what it is anyway)


but in my experience the only place you need this kind of stuff is inner loops


cljs.user=> (map println #js [ 1 2 3 4])

👍 4

people have written games and interactive applications that perform reasonably w/o bothering with this stuff


Hmm, alright. Well I’ll have to look further into their claims and what they were working on


if you know what you are going to do and you know it requires primitive arrays and hand written loops you can do that is all I'm saying


if you don't know what you are going to do - then I wouldn't worry about it


and just write your game or interactive application - you'll probably be ok


Sure, I honestly don’t know yet. Probably something with WebGL/Canvas/shaders


if all your serious stuff is in WebGL/shaders then ClojureScript probably won't be much of bottleneck


if you'll be shuttling buffers around so you can't use ClojureScript data structures here anyway


Makes sense


Well I guess I’ll just have to try some things out 🙂


Thanks for your thoughtful responses everyone


@mruzekw I’m just in the process of porting react-three-fiber examples to cljs, so far it looks plausible (and the code does a lot of interaction with three.js) - at least the dev experience will be on par with writing js+jsx - haven’t done any performance comparisons yet

👍 8

Thanks! Will give it a look


Three.js is definitely on my list to check out


Wow the demos on the JS lib look great!


I tend to hide all interop-y stuff under helpers namespace and the main code reads quite well, so even Cursive does not complain 🙂


haven't been following react-three-fiber that is pretty cool


I’m also a musician, so I think it would be cool to hook up MIDI or live sound to a music visualizer


This would probably work for what I’m looking for


@dnolen react-three-fiber is pretty recent project, they build on the fact that you can write custom reconcilier for react, so you can manage other structures in react-way, not only DOM


@mruzekw if you want to learn it you could take some demos and help me port them - the scaffold is in place, it should be just a matter of rewriting their js code into nice cljs 🙂


Sure! I can take a stab at a couple to learn

👍 4

I whipped up a quick example of using react-three-fiber with helix, too 😄

👏 4