Fork me on GitHub

@cfleming and @phill: LightTable and NightCode are what I've seen for ClojureBridge as well, but I think LightTable is no longer an option and NightCode, though great in other respects, now forces use of Parinfer


@lspector Nightcode source is really small… you might consider forking the repo and changing out Parinfer.


@tim792 I've discussed it with the author and apparently he redesigned it all around Parinfer and it's essential now


@lspector I didn't catch it, what don't you like about parinfer? I find it to be pretty efficient.


@john Parinfer breaks ordinary typing skills and moves brackets around on its own, all of which I find deeply counterproductive.


And if you cut/paste code that might not be balanced yet (which I do all the time, and see students doing all the time) it makes a big mess.


@lspector I guess there's a curve there. But it removed a lot of key strokes for me once I got used to it. Ah yeah


There's the broken formatting thing


Those keystrokes are features, not bugs to be removed IMO


With regard to learning how to appropriately manage parentheses?


I guess it's a little opinionated about some code structures that some might disagree with


Yeah, parentheses are part of the language, and knowing where they should go and typing them is part of properly learning about and thinking in terms of the language. Indentation isn't part of the language and it shouldn't be driving anything (although it's very handy for *seeing* the structure of the code you've typed, which is why I think that it's crucial to have a re-indent feature).


Plus, new programmers especially (and me too!) have enough to think about without having to deal with a new way of typing or a mysterious gremlin that adds/deletes/moves around brackets that I didn't want added/deleted/moved around.


I can appreciate that Parinfer is a really clever hack, and if someone really cares about keystrokes or likes it for some other reason then that's swell. But I've tried to give it a good try on a couple of occasions and found it completely unusable for the way I edit code. And I think it's particularly bad for new programmers for the reasons above. I've watched students who had to use NightCode because they couldn't get other setups working get so frustrated that they cut/paste to a plain text editor and then cut/paste back into NightCode so they could edit in a sane way (albeit without bracket matching or re-indentation as they're editing).


I absolutely love Parinfer, and at least to me, I feel it uses indentation only as a way to reason about Parenthesis. It's not like I'm working with indentation, but indentation makes it friendly to reason about the sexps and also visually pleasant with some very good conventions (all mental burdens I don't need anymore). I rarely paste unmatched code when I'm studying or looking for things and if I can't copy it directly in a structured way (I often copy sexps with expand-region, which ensures structure), I type it (because I like to type and it helps me to get it, nothing wrong with copying and pasting, just different perspectives). I can see how asking students to type all codes could be very rich for lisps, but it could also add a heavy time burden in a class situation. Parinfer was the thing that really made the parenthesis fade and the structure rise in my experience, so its interesting to see someone else with a very different experience. When I first saw it I was like "this should be standard everywhere" but I guess everything has its drawbacks.


@anantpaatra that's interesting and I see that it's great for some people. FWIW when I'm cutting/pasting while coding it's often because I want part of an expression I put in one place to be in a different place, and the part I want to move is unbalanced, and it's simplest to just copy/paste text and then patch up the brackets (aided greatly bracket matching and re-indenting). I do this kind of thing all of the time, and I see students doing it too.


I ususally use cleverparens & regular lisp-mode interactions for editing.. in emacs that is..


Once you get used to thinking of code as a tree-like structure rather than text it becomes very natural to move bits around


@minikomi I believe that's true for you! Not for me, though I've been writing and teaching Lisp for decades. Editing text free-form is vastly better for me. And for new students it's important to be able to edit in a natural way before they get used to any new way of thinking.


of course, just throwing in my 2 cents to a pretty subjective topic!


Me too! Anyway, I think I found the solution I needed: If someone wants to follow the Clojurescript Quick Start instructions but in place of "your favorite text editor" use an editor that supports re-indentation and bracket matching, and is as simple to install/configure/learn/use as possible, I think one good current answer is to use VS Code with Calva Clojure Formatter and Clojure Warrior (for the bracket matching).


So the problem is in the Copying, not the Pasting! If the editor happily Copies imbalanced stuff, then what is Paste to do? This is something Paredit does really well. It binds the usual cut/copy keys to an improved function that snags only a matched section.


Hi, I’m in need of some advice in regards to advanced compilation. I use D3 from cljsjs and I’m not having an externs issue, but rather an issue with accessing properties in the JS data I pass to my D3 force layout. In D3 you often access properties of the current datum to have e.g. an SVG text element contain information from the datum. See example below. What could be the reason for “undefined” being returned? I’ve read that aget shouldn’t really be used this way, so I’m reluctant to change to using it and I personally prefer accessing via In development mode with optimization = none, all alternatives works just fine. (clojurescript v1.10.439) Any help appreciated!


The properties are probably being munged by GCC. Give goog.object a try instead of aget (or


@phill improved is in the eye of the beholder. When I copy some unbalanced stuff it's because I want to copy that unbalanced stuff. It would make me unhappy if it thought it knew better and instead copied something else.


@mokr if this is advanced, can you try (fn [^js d] ...) ? See if that works?

Braden Shepherdson16:01:44

I asked this weeks ago, before the holidays, but things were pretty quiet and I got no answer. I'll try again: my big goal is to have CLJS output a Closure library for inclusion in a larger project. using :modules gives a self-contained file, but it includes what appears to be the entire Closure base library at the top. I really want to output just my own namespaces, with its few lines of code and goog.provide('my.namespace');. I can't find a flag to do that, though.


@braden.shepherdson if it's in the build, you need it

Braden Shepherdson16:01:26

sure I do - but I've got a big Google Closure project with its own build system that will take care of it.


right so was missing that detail in your description


we output individual files always


so then why not just copy over what you need


Google Closure can resolve deps pretty easily on it's own now from CLI


so I think you could probably just put your stuff on the path


and do one build no?

Braden Shepherdson16:01:59

meaning for example out/my/namespace.js


@tkjone yes watches you can add but not using the native atom builder method... i think that's because watches are more sophistically controlled in the background/under the hood. kinda like having a setter or getter method for a more complex data-type

Braden Shepherdson16:01:25

I didn't notice those files, those are exactly what I'm after.


right, so the most basic build never even goes through Closure


these files are Closure compatible and you can just do your own thing

Braden Shepherdson16:01:02

yeah, the out/ tree should be workable as input to the build system. I'm trying to mate CLJS modules into Google's build system, Bazel, and all the infrastructure for optimizing and shipping JS.


@braden.shepherdson the only thing that will cause trouble here are patterns Google Closure of course doesn't really support


like foreign libs


but if you're doing a purely Closure oriented thing - everything should be just fine

Braden Shepherdson16:01:51

it's mostly Closure all the way down, and where there are foreign libs they already have Closure externs. mostly it's my own CLJS code, but I need to play nice in the Closure-based expectations of the JS bundling and serving infrastructure.


externs aren't the issue though here


foreign libs have no corresponding feature in Google Closure


these libraries do not have goog.provide or goog.require


ClojureScript makes that work


w/o any help from Closure


but that means that those things won't be understood if you do this with Closure directly

Braden Shepherdson16:01:30

oh, I see. I misunderstood you, but there's no problem here.


@sova Interesting. Curious, why do you think they were added as an arg to the constructor? Is this to keep in sync with Clojure Atom?


i don't think clojurescript cares at all what clojure is doing (left brain / right brain ... utah and massachusetts ) but there are methods in clojure.core that are also "don't use this, it's just under the hood stuff " ... I wondered how atoms were implemented in cljs so it's cool to notice that they have the watches built in as a constructor piece. i'm not sure what all backflips one needs to do to make something that is theoretically and research-fully immutable actually/practical/usable immutable. if you consider how javascript is single-threaded, that might be a clue into why the implementation would look very different than the one that lives on the JVM. it's probably the most efficient way for a single-threaded process to respond to events (atom changes) and serve out updates accordingly.


@tkjone and maybe someone more experienced and knowledgeable knows how come


Indeed. I deep dove into Atoms and it was really fascinating to see what was going on under the hood! Thanks for your input 🙂


Hello y'all! What are you using for doing routing in the browser?


currently bidi

👍 5

@victorbjelkholm429 Accountant is my current weapon of choice

👍 5

@hlolli Thanks, your suggested (fn [^js d] …) solved my property access issue. Thanks to the others that responded as well.

🙂 5
Kelly Innes23:01:28

Hi! I have a question about lein-cljsbuild

Kelly Innes23:01:57

Specifically: is it possible to set it up to give the output app.js bundle a unique hash for caching purposes, like app.[sha].js

Kelly Innes23:01:32

Webpack does this for JS/React projects, although it also has to process and output the index.html file. Wondering if there's a similar setting in lein-cljsbuild?


@kinnes There is a new :fingerprint compiler option in the latest release, which I believe does that

Kelly Innes23:01:17

🙌 Awesome! I'll give that a try.

Kelly Innes23:01:44

Apparently shadow-cljs can also generate the hash, but I haven't ever tried using that.


We need some docs on the :fingerprint compiler option