Hacker News new | past | comments | ask | show | jobs | submit login
Pinball implemented using Squint, a ClojureScript dialect (squint-cljs.github.io)
137 points by Borkdude on Nov 17, 2023 | hide | past | favorite | 25 comments



For those who don't know:

Borkdude is a fairly big name in the Clojure community, most known for developing clj-kondo (static analysis tool used by clojure-lsp) and babashka (a Clojure interpreter built atop GraalVM native image so you can have fast startup times and decent performance writing scripts in Clojure).

"Squint" is a ClojureScript compiler of his that transpiles ClojureScript directly to JS while introducing as little runtime overhead as possible. For instance, the usual PersistantVector, PersistentHashMap, etc. data structures compile straight to ordinary vectors and maps in JS. This means they are technically mutable and have slightly different semantics underneath. The goal of Squint as far as I can tell is to be akin to ParenScript but for Clojure (a subset of the language implemented that compiles straight to human-like JS code).

ClojureScript itself is a compiler that takes Clojure code and transforms it into JS code that is processable by Google Closure Compiler's advanced optimizations. Unfortunately, betting on Google Closure proved to be bad, given that next to nobody in the modern JS ecosystem has used it in years. It also was the biggest reason for painful NPM integration in the past, though this has been mostly fixed thanks to externs inference by the CLJS compiler and tools like Shadow-CLJS that make use of Babel to run various transformations and pass NPM code into Closure's simple optimizations rather than advanced. This gives you bundles that are more or less equivalent to using Webpack with the terser plugin, but you still have painfully long compile times and the usual caveats of using Closure compiler.

Borkdude also has a CLJS to ES6 compiler called "Cherry", which behaves much more like ClojureScript compiler than Squint does (e.g. it actually implements persistent, immutable data structures and there is a runtime associated to it).

Squint has been gaining a bit of interest from ClojureScript developers since it theoretically offers the past of least resistance if you want to make use of "modern" JS tooling like Vite, esbuild, and so on. It also frees you from the externs issues that plague ClojureScript since you are no longer passing everything into Closure compiler.


> Unfortunately, betting on Google Closure proved to be bad

What is the actual practical implication of this? As far as I understand, ClojureScript runs fine with Google Closure and I'm not sure why I'd want to switch compilers.


I think this article does a decent job of highlighting many of the reasons why Closure has fallen into obscurity. https://effectivetypescript.com/2023/09/27/closure-compiler/


That's a very interesting post.

I like closure compiler. It is somewhat related to GWT (which also perform similar manglings of names but since compilation from java means there's no expectation of preservation of field names, it doesn't come out as bad).

On the other hand, i also see why the npm ecosystem (and in general, the javascript ecosystem) isn't suitable for large scale systems programming. The fact that using a module from npm does not guarantee that the "original" source is part of your compilation, seems ass backwards to me.

I like the system that closure compiler implements, because it clearly delineates between source artifacts and compiled artifacts. It also pushes modules to "export" symbols, rather than by default export everything.

If only the javascript users from back when NPM was in their early days actually embraced the concept of compilation units, closure compiler would've been the gcc of the web development world.

It's a lost opportunity to have left it languish, since the compiled output is vastly superior to anything webpack or any other current minifiers can produce.


Very exciting! Also here is link to cherry: https://github.com/squint-cljs/cherry


interesting. I have always wanted a language with s-expressions that pretty much maps 1-1 to javascript in a way that makes macros possible and usable. maybe this brings us closer to that.


Thank you for this context


And not a single :require or outside library. Also, this pinball demo CLJS code seems to be being compiled directly within the browser. Want!

Let's go further. Imagine, a Clojure that directly produces WASM, without JS, without Google Closure. A Clojure that can target the browser and bring in NPM modules with alacrity, like shadow-cljs does today. This approximates the most forward-looking path for Clojure on web technologies I can think of at the moment.

Borkdude appears to have boundless energy. Just maybe, in the Clojure community, Borkdude is what comes after Chuck Norris memes. Does Borkdude ever sleep?


Borkdude is a misnomer. He should really be called the Borkcollective.



I've never used ClojureScript, but if I'm reading this correctly the big difference between it and Squint is the representation of data structures where ClojureScript uses something clever and Squint uses basic JavaScript structures.

How are you finding the implications of that decision? Thoughtful data structures choice seems to be one of Clojure's biggest advantages so I'm assuming there is a lot to dig through here.

Also, thanks for being a star. I nearly started this post with "Wow, what a neat beginner project, welcome to the Clojure community" but my grin threatened to hurt my face so I gave up on that idea.


This means that if you use some third-party code, it may work funny if it hits one of the differences. OTOH it should be somehow faster.


The Wordle clone is less exciting but you can scroll down to see the source code and JS output more easily: https://squint-cljs.github.io/squint/?src=https://gist.githu...


I had a lot of fun using squint with solidjs. It pairs so well with minimal, focused libraries. Maybe it doesn’t give you any superpowers but make code a little cleaner and steer you away from few traps.

On my “nerd snipes” list I have project that merges squint and hwy framework. It sounds like bleeding edge for the sake of bleeding edge, but on the other hand sounds so compelling!


Lots more fun than I expected on my iPhone. Thank you


It runs far too quickly on Firefox for whatever reason.


Probaly not a browser issue, looking at this line of the generated JS:

> var physics_scene = squint_core.atom(({ "gravity": [0, 0], "dt": (1 / 60), "balls": [], "obstacles": [], "flippers": [], "score": 0 }));

I think it run faster for any refresh rate higher than 60hz.

Changing the value from 60.0 to 120.0 in this line:

> :dt (/ 1.0 60.0) ;; slow down sim

and recompiling, makes it run correctly.


Is there a way to get the refresh rate programmatically?


Yeah, you drive things with https://developer.mozilla.org/en-US/docs/Web/API/window/requ... since it's dynamic


I was not able to find one, but this js snippet:

> https://gist.github.com/capfsb/3fd1b700b4732debb29aefd576cf5...

correctly reports 240hz for me.

The fun thing is that 240 makes everything too slow, whereas 120 works fine.


Hey borkdude, this looks great! I've checked Squint and Cherry before but got confused about why 2 separated projects?



I mean this game is a rip-off of https://matthias-research.github.io/pages/tenMinutePhysics/i... So if you like the game then give the Matthias Müller-Fischer some love.


Rip-off might be a strong word. That blog is referenced in the first comment of the code, and obviously this is made in a different language, so at most i'd call it a reimplementation.


Very fun game




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: