Fork me on GitHub

nah, you both have slightly different profile pictures, so not a bot that just copied an avatar, so I suspect you are both spammers


it showed up as a double join in the slack ui "Nicole Kathrine joined #beginners along with Nicole Kathrine." but if I click on each name and view full profile and click the '...' I can see the member id which is different for each one


Please do not engage with spammers. Just let the Admins know and we'll deactivate them and clean up.

❤️ 8

They mispelled Katherine. Dead giveaway.


When using lein's :profile mechanism - does providing a :user profile override whatever exists at .lein/profile.clj ?


Hey folks. I just installed Emacs (for the second time. I tried it for a week or two last year) and Doom, and I am going to try to see what CIDER involves, because I heard Emacs+CIDER is the best way to do Clojure and ClojureScript.


...but I don't know what other tools I need, besides having tried Leiningen and FigWheel when I tried CLJS for a hot minute last year and went through the quickstart guide and then wrote one tiny (but useful to me) program.


I have heard of npm and shadow.cljs as well, but I don't know if I need those, and if either of those tools would be instead of either Leiningen or FigWheel or along with them or what. ...and if there are other tools I should use (instead or in addition). Can someone please give me a quick breakdown of what tools do or even just recommend a set?


Note: I want to focus on clojurescript right now, but I am pretty sure I will want to do Clojure soon.


Cursive or VSCode is more beginner friendly in my opinion, but I won't stop anyone from learning Emacs (which is the editor I use)


You have two choice of tool for ClojureScript, either figwheel-main with tools.deps or shadow-cljs


In theory though, you don't need anything else but Java and Clojure. Clojure now comes with a dependency manager called tools.deps. With it you can add a dependency on Clojure and ClojureScript.


But because using the ClojureScript compiler directly is difficult, and because people want a good in-browser REPL with hot-reload, everyone ends up adding either shadow-cljs or figwheel-main to their setup.


I'm taking the same approach with Blender, and being farther along the curve I'm happy with my choice there.


I don't mind the learning curve if it's the best tool.


What about Leiningen?


The difference between the two is that figwheel-main works directly with tools.deps and is "closer" to the standard ClojureScript compiler. Shadow-cljs has more magic on top and handles everything itself to make things easier.


and is it true that figwheel does cl and cljs while shadow only does cljs?


Hey @factorhengineering. The tooling can certainly be confusing. There are many tools and they overlap in slightly different ways


Leiningen is an alternative to tools.deps, it can also be used with figwheel-main, but I would say it is losing popularity, especially for ClojureScript, I wouldn't bother with it.


If I ever figure it out I will make a graph...or a flowchart...or something.


It is true yes. But you can happily use shadow-cljs for ClojureScript and tools.deps or lein for Clojure.


Figwheel-main is also ClojureScript only, but it integrates directly with tools.deps


Leiningen going away? Wow. In my quest to pick a language to learn, a huge thing in the plus column was supposed to be that while other languages need a confusing array of tools, in clojure(script?) you only need one: Leiningen.


Didibus you’re offering more options w/o explaining the delineation


I did come across the fact that figwheel was replaced with figwheel-main. ...but that change made it cljs only?


...or...if it's browser reloading I guess it was only ever cljs?


Okay, so there’s some misconceptions there

eccentric J03:05:08

At this point VS Code, Atom, and neovim all have really solid clojure offerings at this point — use whatever you’re most comfortable with.


Figwheel is a tool specifically for helping with developing ClojureScript applications


Figwheel first started out as a plugin for leiningen


I just spent, seriously, about 20 hours over multiple days figuring out how to install Emacs and Doom. I'm going to stick with it for a while at least. lol


The latest version, figwheel-main, is less coupled with leiningen


What were my misconceptions?


That figwheel is about anything other than clojurescript development


Ah. yes. You could see my figuring that out in the middle of my post back there. Ha.

👍 4

The stock ClojureScript compiler doesn’t handle hot reloading, or a bunch of other things that are nice to have for development


I think I read that shadow.cljs does the hot-browser-reloading just like figwheel.


Figwheel builds those on top of it


So...they're in direct competition, then?


Yes, in some aspects


What do you use?

eccentric J03:05:49

I had worked with figwheel, figwheel-main, and shadow-cljs for a TUI template. Shadow-cljs was by far the easiest, most streamlined, and best documented experience but they’ll all work… eventually 😄


The important thing is that figwheel only handles making ClojureScript development nicer - it doesn’t handle installing dependencies, or building a class path, or any of the things that a tool like leiningen does for you


and is CIDER a given? I'm assuming all the options available to me (given Emacs as a starting point) involve CIDER


Shadow-cljs is an all-in-one solution - it handles dependencies, build configuration, compiling, development things like hot reloading


It also has built in support for using JavaScript libraries


Is there a way to quote in Slack?


You can copy + paste it with a >


I see 'start a thread', but that sounds more heavy-duty than I want. lol


Ugh I’m on mobile


> there’s a thing in the WYSIWIG as well for quoting


All of these tools can be used with nREPL + CIDER


With Emacs you want to use Cider for sure.


> figwheel [...] doesn’t handle installing dependencies, or building a class path, or any > of the things that a tool like leiningen does for you ...but that extra stuff could be handled by the (relatively new?) tool.deps, though, yes?

eccentric J03:05:29

Cider handles connecting emacs to an nREPL server. Shadow has built in support for creating an nREPL server when watching a build to let you interact with the running app.


Yes, you can use leiningen or tools.deps with figwheel to build a project and manage dependencies


What's nREPL? Is that yet another thing I need to install?


I don't remember it from before


It’s just a protocol for connecting to a REPL. It’s what CIDER and a lot of other tools use


Don’t worry too much about it


The point is that all of these tools can be used with CIDER

eccentric J03:05:05

nREPL is a networked REPL. It’s what lein starts when you run lein repl but liliactown’s right. Not particularly important.


I'm not quite getting what tools.deps does. It's in direct competition with Leiningen? ...and shadow.cljs also can take their place?


• you can use shadow-cljs to build, manage your deps, and do hot reloading • you can use leiningen / tools.deps + figwheel for building, managing your deps, and doing hot reloading


(as someone who has done Clojure for a decade but has hardly touched ClojureScript, this is fascinating because the cljs ecosystem has changed dramatically over that time and I wouldn't have the first clue what to recommend to a beginner!)


Tools.deps just installs dependencies and builds a class path. Leiningen does much more; it has a whole plugin system


shadow.cljs is easier/better, but leiningen/tools.deps + figwheel has the advantage of also working with Clojure?


Figwheel has nothing to do with Clojure


Duh. Sorry. Knew that and immediately forgot.


But yeah, leiningen or tools.deps is also used primarily for Clojure development


(tools.deps is "just" a library -- it's used by the "Clojure CLI" and you'll see references to deps.edn which is "just" a description of dependencies -- like the :dependencies vector in Leiningen's project.clj file and :aliases which are a bit like Leiningen's profiles)


It’s also fine to have shadow-cljs for ClojureScript and another project setup (leiningen or tools.deps) for Clojure


When you (or was it didi...?) said Leiningen was losing popularity, was that just for ClojureScript development, or for Clojure as well?


Leiningen is the oldest and still most popular build tool for Clojure.


Sounds like the best tool for Clojure still, based on what I've heard here.


The Clojure CLI / deps.edn is newer but it is official -- from the core team -- whereas Leiningen has always been a community project.


Use whatever the tutorials you are following suggest and see how you get on, would be my advice.


There's some fundamentals to understand: 1. ClojureScript dependencies are supposed to be deployed to a Clojure repository such as Maven. 2. tools.deps lets you declare dependencies from Clojure repositories such as Maven. 3. JavaScript dependencies are not in Maven by default, but in NPM. 4. Some people have gone through the trouble of uploading JS dependencies to Maven, this is known as the cljsjs repo. 5. ClojureScript and JavaScript dependencies that are in Maven can be declared with tools.deps and used directly from ClojureScript without issues. 6. If you need to use a JS dependency that is not in Maven, things get complicated, because JS dependencies have no common standard. 7. Shadow-cljs is specialised in handling JS dependencies not found in Maven, and making them easy to use. 8. The ClojureScript compiler can also pull down npm dependencies, and use them, but it often requires more fiddling then shadow-cljs. 9. Beyond dependency management, there are other things we want our build tools to do for ClojureScript. Some of those things are: hot-reload of ClojureScript, HTML and CSS. Simple dev server to serve our website from. And manage various compilation configurations for dev, prod, etc. 10. Figwheel-main handles all the things in #9 but doesn't manage dependencies at all. It leaves that up to tools.deps and ClojureScript to do so. 11. Shadow-cljs handles all the things in #9 and also handles JavaScript dependencies from NPM.


(Thanks to @didibus @lilactown and now @seancorfield for coming to my rescue BTW. I'm a little burnt out from the EMacs and Doom installation being so hard to figure out. lol)


yeah a lot of this is being presented with no pedagogy whatsoever


So for a newbie who wants to do CLJS but probably also CL, would you recommend shadow.cljs or lein(+figwheel in the CLJS case)?


I would recommend shadow-cljs and following a tutorial


and then when you want to learn CLJ (note the J, it’ll help with googling - CL means something else)


setup using a Clojure tutorial and whatever tool they recommend


and then coming back to lein later (and never coming back to fig)? OK. I guess my hope of learning one set of tools for both is not quite the best option. Good to know.


Still reading didibus' post. Not familiar with NPM or Maven at all.


Ignore that wall of information -- not relevant for the questions you are asking at the moment.


Are they like git? (very basic understanding of git here)


Nothing like git, no.


Just ignore all that npm/maven stuff -- not important for where you are right now.


figwheel and shadow-cljs definitely overlap

eccentric J04:05:00

You’re right. Trying to get that look right

eccentric J04:05:22

Abandoning the circles… not the right solution I think 🤷


If shadow handles all the things mentioned in points 9. and 11. above, then what is tailwind?

eccentric J03:05:19

(just made it public, may need to refresh)


@jayzawrotny Actually I don't see how that applies at all. 😕


tailwind is a CSS framework and completely unrelated to any of the tools discussed so far. shadow does not give you any out of the box styling for your website

eccentric J03:05:38

Aww bummer, I was trying to visualize the relationship between emacs, cider, shadow-cljs, your app, and nrepl. Then show how the various build tools overlap. Anyone have any suggestions to make it more clear?


@seancorfield If that Maven/NPM info isn't applicable to me now and shouldn't affect my choice of tooling, then sure I'll ignore it. 🙂 ...but I really don't mind considering the end game when deciding on what to learn.


Part of the problem is that there is a HUGE ecosystem in the background of all this (Clojure/Script) but it only really becomes relevant when you start to think about publishing libraries really. So it's all a bit confusing when you're getting started.


So if that info is applicable to going to shadow or not, please do let me know.


Maven is where Clojure(Script) libraries get published. NPM is where JavaScript libraries get published


All of the tools allow you to install Clojure(Script) libraries. Different tools have different ways of handling JavaScript libraries


shadow-cljs has the easiest path to use JavaScript libraries from NPM


@jayzawrotny It seems like you linked me to a diagram on a completely different subject TBH. Is the image supposed to me about accounts and passwords??

eccentric J04:05:00

Try refreshing. It’s directly related to this subject.


@lilactown Are there any NPM libraries in particular you think I would miss if I miss out on NPM?


@jayzawrotny If I click on the whimsical link instead of the preview window or whatever that is, yes I get a completely different image, and yes it's helpful. 🙂 Is there a reason the lein and figwheel boxes are kind of just floating in the middle, though?


OH...I see you're still working on it (and I see that I can see you working on it!).

eccentric J04:05:38

I’m working on that part now to list features specific to each.


I can’t predict the future, but often what happens is: • You have a problem with your CLJS app you want to solve • You google for a solution • You might find a solution in JavaScript that says, “use this library” • That library is installable via NPM


the ability to use JavaScript and ClojureScript libraries easily is a huge win IME


YMMV - many people prefer solutions where it’s a bit more DIY


OK, so learning shadow.cljs and, later, Leiningen is really best. OK. I mean I'll have to learn the CL vs CLJS differences at that point anyway.


So focussing on CLJS then, is there any reason to go for a thing I came across called Tailwind? I think it's for CSS but I just heard from didbus in the big list that shadow.cljs (and figwheel for that matter, but it seems like I don't need to bring up figwheel since it's not in the running anymore) does CSS.


Hum, the tools don't matter too much. Its best you just find a good tutorial. They all do the same thing, and you can change from one to another pretty easily, so you're not locked in to your choice.


Then again, I heard of Tailwind when I was trying to figure out what CIDER was and watched part of a YouTube video of a person using Emacs+CIDER+shadow.cljs+Taliwind. Wha?


For example, this guide seems pretty straightforward to get started with: It shows making a small reagent app. Uses tools.deps and figwheel-main. There's probably another good one that would use shadow-cljs as well out there.


One last tool I've heard of, and maybe it's just built right into CLJS anyway is...I'm blanking on the name but it's for writing HTML as CLJS.


Do you know what it's called? I would know it if I heard (read) it.


That's it.


Is it a separate install? Does shadow.cljs do what it does anyway?


@jayzawrotny Aww...the Venn diagram disappeared.

eccentric J04:05:12

If you use reagent, a react wrapper for cljs, it will make use of hiccup syntax to build your components.


Hiccup is "just" a library.


hiccup isn’t exactly what they want... they probably saw reagent, which reuses hiccup’s syntax for describing elements in a component


Right, I just wanted to clarify it isn't some separate tool they need to learn 🙂

eccentric J04:05:49

@lilactown Doesn’t your hx lib use hiccup as well?


hx does but I am archiving it :) it’s successor, helix, does not


Hiccup is like Clojure, there's more than one implementation 😝


So much churn 🙂 And we wonder why beginners get so confused?


I've tried to learn cljs several times over the last five or six years -- and it's different every time 😞


The syntax is called hiccup, and hiccup is also a library for parsing hiccup, but there are other libs that parses the hiccup syntax as well (some with various slight additions to the syntax as well)


The "hiccup" library for ClojureScript is called hiccups as I recall?


a few people used hx so I don’t feel bad archiving it


Ya, ClojureScript is hella confusing :p, JavaScript is hella confusing to me as well, which is part of half my confusion with ClojureScript. I honestly am impressed at people who are learning to program with JavaScript ecosystem first


And I remember learning reagent at one point and there was a hiccup syntax library for that too -- with yet another different name?


reagent includes a hiccup parser out of the box


among other things


ClojureScript is relatively stable, but it’s also feeling the pain of keeping pace with the rate of development w.r.t. web UIs in general


Relatively stable now. It certainly wasn't several years ago.


I would say it’s more unstable now than it was a year or two ago :P


I help maintain a 3 yr old, 50k LOC ClojureScript app at work. There are many different decisions I would make today given what the state of the art is and the collective wisdom we have gained since starting it


JS still feels like a huge moving target, but browsers compatibility seems much better now


I just relearn CSS, and flex and grid layouts are a god send. I used to do table layouts or floats which were so confusing


developing a web UI that meets the needs of todays users is just a beast of a project, and requires a lot of 3rd party code to be economical. that means churn as 3rd party solutions meet their limits or lose support

eccentric J04:05:00

looks up helix

eccentric J04:05:01

Ooh nice! What made you switch from the hiccup syntax if I may ask?


allocating vectors at runtime was too slow

👌 8

Ah, sablono is what I'm thinking of from when I was doing ClojureScript...


Ya Sablono is what I'm currently using for my toy cljs app.


...we built a p.o.c. with Om and then rewrote it with Reagent and we started using Sablono because of its Hiccup-like syntax.


But there is also a hiccups I think. But it seems Sablono and the baked in reagent parser are the most used ones


Yes, I mentioned hiccups above.


When we first tried cljs, it was 2013 I think. The Wild West.


yep, a lot has changed since then :) the tooling is definitely better


Like FHE tho' I have no idea what I'd start with today if I was just trying to learn cljs, even after a decade of Clojure.


I'd start on but I don't think that gets me very far (does it?) and beyond that it's still pretty crazy...


I just got started with it, first time. I did raw ClojureScript with no tools first and only tools.deps. Then I added figwheel-main, and then I went with rum for UI components.

eccentric J04:05:53

I was reading that the other day. The guide is ok but it’s missing a lot of goodness like reloading, serving public files + reloading CSS, releases vs dev watching builds, and simple npm deps support. I’d still pick shadow well over the other options for now.


it’s sort of like starting a backend system using Clojure


Relying a lot on pure ClojureScript and cljsjs for now, as I don't need anything fancier from npm yet. I suspect when I do, I'd either try the new bundle thingy (though that version of ClojureScript is not working on figwheel-main right now). Or I'd move to shadow


like, Clojure is sort of one of the last things you need to know...

💯 12

Ya, I think it's a bit the struggle with being hosted. Like most of my learning I'm having to do for ClojureScript are really about learning the JavaScript host


I've seen a few people start out now with babashka instead. Because getting started with it is most straightforward.

eccentric J05:05:43

Interesting! The more roads in the better?


Choice is good. Choice is also confusing. 🙂

💯 8

Choice is kind of one of Clojure's strength honestly. Like Clojure often call it "reach". It runs on so many platforms, it can leverage so many existing tooling and framework and libs, and it adds more of its own to the mix.


But navigating it all when you don't know what you want is difficult


Probably most people don't even know if they want to learn Clojure or ClojureScript first 😝


And then the language itself is all about given you infinite power. Quite the opposite from say Pythons attitude that there should be only one way to do anything. This power manifests itself in even more choices.


For me, that's the fun of it. I like trying lots of different things or ways for doing the same thing 😝. And I even like coming up with my own. Its a way to be creative. But it's definitely more confusing.

👍 4
eccentric J05:05:50

That’s true. Everyone talks about all the roads that leads to Rome. No one discusses that one-way dirt road near where I grew up.

eccentric J04:05:26

I can bring it back, but it’s a bit off


What you need to install are: JVM, Clojure, Emacs+Cider, NPM.


And your choice of figwheel-main or shadow-cljs

eccentric J04:05:41

I would highly recommend shadow-cljs for your position given that it can interact with cider out of the box, is a standalone tool, is fully featured, and well documented.


OMG Emacs is driving me bananas right now. I'm practicing using it to document all the installation steps I have to do on a fresh computer (my wife's) to install everything, and I do NOT understand the undo system. I mean I thought I did, but suddenly both the undo command AND the redo command both undo and I can't redo all the things undo destroyed. Sorry. Off topic.


There's an #emacs channel if you have specific questions for Emacs


I've got Emacs, git (for installing Doom), Doom (not required, I know, it just sounded good), adoptOpenJDK V8 so far


Next going to figure out where to put the cljs.jar file, and figure out what the heck using CIDER entails (I know it comes as part of clojure-mode in Doom Emacs if not vanilla Emacs).


Did you install Clojure ?


You should not manually download and place the cljs.jar


You should create a deps.edn file and declare a dependency on ClojureScript instead


I just noticed this thread. I did download the cljs.jar file linked to directly from with text to the effect of "you need the standalone CLJS JAR file". I just parked it somewhere and haven't done anything with it, though.


I did install node.js and then created a project using a command using npx that is in the shadow.cljs installation instructions. With all the other things that were automatically install, any chance it would have automatically installed cljs.jar?


Its likely shadow-cljs includes it ya


you're learning a lot of things at the same time


personally i'd just go one at a time but your call


@jayzawrotny gotta have that Venn. appreciated even if imperfect. 🙂 By the way, what would the block diagram at the top look like for Lein+FigWheel vice shadow.cljs?

eccentric J04:05:50

Added back the venn, I think it’s more accurate now

eccentric J04:05:12

Ultimately you would be running figwheel through lein and it would be creating a cljs repl you could connect to through cider in emacs. But if I recall, the process wasn’t as streamlined as shadow’s.


OK. I barely noticed this thread thing btw. Seems good as long as a person doesn't open more than one side thread. lol ...and as long as the discussion wouldn't benefit from extra people chiming in.


Is there any way to save a image to refer to later?

eccentric J04:05:20

Not sure if guests can but here


Too bad none of those circles fully encompass any of the other circles. Sigh. lol

eccentric J05:05:28

A core thought often seen throughout Clojure is to build the simplest tool that solves one problem well. Shadow solves cljs really well, lein solves clj but can do cljs with a plug-in like figwheel, deps.edn only does deps.

eccentric J05:05:39

@factorhengineering Hmm actually it would be more like this in terms of functionality.


does.edn?? That's a new one on me.

eccentric J05:05:19

deps.edn or tools/deps that’s the more recent tool someone mentioned earlier

eccentric J05:05:49

(I had a typo)


@factorhengineering If you are already familiar with an editor that has a decent Clojure/Script integration, I wouldn't bother trying to learn Emacs as well..


(I used Emacs 20 years ago and moved on to other things, then came back to it when I learned Clojure... but switched to Atom back in 2015 and I've been very happy with that decision 🙂 )


@vale You're totally correct, but I'm just trying to start with the end in mind, meaning I want the in-the-end best set-up and not the at-first best set-up. I feel like doing anything else wastes time learning things I won't continue to use.


As for other editors, I used NotePad++ just trying to get syntax highlighting when I gave CLJS a shot last year...and I didn't even get that to work. lol


The only other thing I've used is Eclipse for Java years and years ago.


i'd just learn setting up a clojure project first, then add cljs to the mix and finally switch to emacs if still interested


setting up cljs and emacs sounds overwhelming to me and i've been using clojure for years


I mean I did get a cljs program (webpage with a bit of text manipulation programmatic magic I needed) up and running, and I did use Leinigen for that (and I also set up FigWheel but didn't really make any use of it). Baby steps for sure, but I don't feel like I need to avoid CLJS.


i don't think you need to throw away lein for shadow-cljs, you can use them together




there's even a shadow-cljs template for lein


I do like the idea of keeping as much in common as I can between working on CLJS and working on CL. ...but no-one above recommended or even mentioned using Leiningen and shadow.cljs together, iirc.

eccentric J04:05:25

You can use shadow-cljs for your cljs and lein for your clj parts. That shouldn’t cause issues.


Thanks to everyone who answered so far.


So my next step is CIDER...or is it? I guess I don't need to get into that until I get partway into shadow?


I still have that lingering question on tailwind and hiccup (unless I missed the answer). Does shadow.cljs do what they were once needed for?


While it is a nice idea to use the same tools for both, I wouldn’t recommend it. Having two host langs with their own ecosystems... you really want to dive into one or the other, learn it well, and then learn the other one.


...or should I set them up?


@krzyzowiec Yeah. thanks for that last push. I was almost there. Yep...Leiningen you're going to have to wait. lol


So for CLJS, learn NPM, shadow-cljs, JS interop, cljs libs, browser info, etc


I'll try a dance with shadow.cljs


Trust me on this, I went down the same path as you. It was very confusing, but siloing them into the Java path and JavaScript path made it very simple. I use Lein when in Java land.


NPM for JS libs, and ...something...for CLJS libs, yes?




(this is why, having done Clojure for a decade, I still don't do ClojureScript -- it is a very confusing and constantly-changing ecosystem as far as I'm concerned!)

💯 4

It’s easier for a JS dev since you are already familiar with that ecosystem. You know NPM and package.json, webpack, etc, so you just pick up the CLJS bits


OK. I won't push for libs yet, but good to know for when I need them. Same thing for Java interop. I feel like I have a slight clue about that just knowing what the word interop means, and I may have even used a tiny bit of it in my program way back.


Not quite sure what you mean by learning 'browser info'.


Learn how to interact with the DOM


You mean parts of a webpage? HTML (+ maybe CSS)?


Yes, all those things that you need on the front end


I did a bit of that with my program too. More to learn when I need it there too.


Then learn to run away from the horrible DOM and use React 😆


So first up is shadow...


What are you trying to build btw?


Right now I want to write a program to help my 1-year old learn letters and numbers and words.


Oh that’s cool.


I also want to write a program for display on a 3-D TV but that is planar but with different scene elements assigned to different eyes.


The point being to make sure that both eyes are working in order to play the game or whatever the activity is.


That would be to try to correct my 4yo's strabismus, to try to do more for her than just wait for some temporary glasses to hopefully fix it and hopefully be only temporary.


I’ll be honest with you, you’re in for a slog from the sound of it. If you want to learn how to build native apps on mobile devices as well... it takes a while. I’d actually suggest fully learning JavaScript first. Go learn NPM, React, React Native, and then come back and learn CLJS after.


That is the most personal info I've shared in online chat in possibly ever. LOL


The challenge is that you absolutely have to know JS and React very well to build something nice to begin with, and then learning Clojure and its build tools at the same time... it would make anyone’s head explode


I did a program in JavaScript once, also around a year ago. I really picked CLJS in order to avoid what I heard were terrible things about JS.


I would rather not learn JS any more if I can help it. ...just reserving that for when I need to do interop.


Hmm. The problem is that there is a wealth of resources for learning JS related things, and a dearth of learning material for CLJS. So when you inevitably have to learn React, where do you go? I learned React using JS, so I only had to translate what I already knew. Your experience may be different, of course, but I don’t think disliking the host language is a good thing because that environment is critical to know. JS has flaws, but it has improved a lot.


I mean I didn't hate making that little webpage I did with JS, but still...I want to use the better tool where I can.


I'm going to press on with CLJS, but based on what you said I won't be hesitant to get into JS if it seems at all like it will be a good idea. Thanks for the help.

👍 4

My end goal is to write something that can be used on mobile and in a browser.


I gather I need to learn NativeScript or ReactNative or something. for that.


I have to say, a quick Google for building a simple browser app with ClojureScript which uses shadow-cljs does not return anything very good.


and no-one EVER starts from scratch


even if it's in the title of their blog post or video


You could try going through it. It uses Leiningen and shadow-cljs.


I am constantly amazed by how terrible people are at imagining how differently other people's experiences and knowledge can be from their own.


Ya, I'm actually surprised at the lack of guides here. I would have expected to see a lot more.


...which leads to 'from scratch' videos that start with 5 tools already up and running and no doubt customized and optimized for the task 11 different ways.


It’s like a rite of passage lol. I learned by reading source code and project templates on github.


If I could ever get through all the tooling set-up and get to the point of actually writing code again, yes, then reading other people's code sounds reasonable.


@jayzawrotny Apparently I can't have 2 side threads at once. If you have posted anything in ours since my last post, can you please post it here in the main thread?


Small question @factorhengineering, any reason why you want to start straight up with ClojureScript? Is it the appeal of building cool useful things right away? Because to learn Clojure I think starting with simpler things like command line applications is probably more approachable. You can even avoid all tooling and just install Clojure and notepad


I don’t know how other people feel, but I am so far from being an expert right now that I’ll wait on writing guides lol. I would like to do something eventually though. It is not a good situation for a newbie.


It's kind of cute that the quick start guide states "On Windows you will need and the" without the slightest hint of where to put the cljs.jar.


Why did it link that? Unhelpful, Slack. lol

eccentric J05:05:15

@factorhengineering You can track threads on the left sidebar which will change color when threads have been updated.


krzyz, I actually might not agree. I think anyone might be able to write a great guide for how to get from where they were just a short time ago to where they are now.


...or maybe it's just a personality thing, and some people are just better at teaching. The one thing I absolutely do not believe, though, is that the more a person knows about a subject the better they are at teaching it. Those two qualities are orthogonal other than the fact that a person can't teach advanced things they don't know yet.


You could probably write a good guide right now.


I agree. Folks who are closer to the beginner experience are generally best positioned to write tutorials for beginners.


I have almost no idea what to offer beginners in a tutorial because when I was a beginner and just getting started, everything was very different and a lot of the stuff I had to read/do is definitely not a good way to go these days 😞


I am pretty dang noobish right here, but even I am writing a guide right now. If I could give my own guide (which currently only covers Emacs, git, Doom, and the right version of Java for CLJS (8, right?) to my previous self from 4 or 5 days ago, I would save him hours and hours and hours and hours.


(fortunately, I feel like I am still a complete beginner with ClojureScript, so these sorts of discussions are very helpful to me)


I would never want to learn Emacs as a beginner tho' 🤯


That's another good point, Sean. Even if an expert is good at remembering every little step and possible pitfall they encountered and laying it all out, the landscape may have changed.


Agree, I find it very hard for me now to relate to the beginner experience. I'm so removed from it, so knowing what's the right advice or level of detail to explain is challenging.

eccentric J05:05:41

@factorhengineering More refinements 😆

👀 4

Wow! That's awesome. But if I thought it wasn't all that complicated before, now I'm completely overwhelmed! 🙂

eccentric J05:05:33

Hahah yeah… there’s a lot of overlap and minor feature differences. Any suggestions to make it more clear?


No. I mean it just is complicated. There are so many options, some of which overlap and some of which compete.


Unfortunately, you can have npm-deps without shadow-cljs...

eccentric J15:05:33

@U1UQEM078 Oh right! If I recall, figwheel and figwheel main support it?


It's supported by regular cljs, so I'm assuming yes


(shadow's support is nicer, though)

eccentric J15:05:56

Updated it. Thanks for catching that.


Thank you for writing that in the first place!


Oh you are on windows hum... I think that's an outdated guide for it. On windows you can use either Leiningen or Tools.deps as well now.


Like right now, between chatting with you I have been to 4 or 5 different places on the shadow.cljs website and I have not found a single clue about how to install it.


Interesting... I might reconsider then. Maybe I’ll do a blog and write experiences a day at a time or something. I learned a ton while trying to write a React Native app in CLJS.


It has been like this every...step...of the way. ...except git. That was thankfully straightforward to install.


@didibus What guide is outdated? The betweentwoparens one you linked to?


I think both guides I linked seem mostly up to date. But I only glanced at them quickly

eccentric J05:05:21

I was going through the Fulcro (a clj\cljs fullstack framework) getting started guide the other day. It’s really good! Covers shadow, writing components, server side, reloading, REPL, and the framework elements etc…

👍 4

@krzyzowiec So that guide is up to date, unlike the guide didibus mentioned?


It’s two years old, but the info still applies today


It’s just basic stuff about shadow-cljs.


Big post incoming. Sorry. accidentally switched to a private chat and meant to post here...

FHE05:05:54  [2:44 AM] This just about made my cry: Only visible to you Slackbot  [2:44 AM] Eccentric J is currently in Do Not Disturb mode and may not be alerted of this message right away. If it’s urgent, ​click here to send a notification now. Keep in mind, if the recipient has all notifications turned off, they will only get your message when they’re back online. How does Do Not Disturb work? Learn more in this Help Center article: FHE  [2:44 AM] You will need: • node.js (v6.0.0+, most recent version preferred) • npm or yarn Eccentric J  [2:44 AM] Do you not have those already? FHE  [2:44 AM] along with:  "`shadow-cljs` is composed of 2 parts: • The;v=3 Clojure library which handles all the actual work. • The;v=3 npm package which provides a convenient interface for running most of the build functionality directly from command line. " Clojars [thheller/shadow-cljs "2.9.8"] CLJS development tools Total downloads / this version 271,299 / 518 Coordinates [thheller/shadow-cljs "2.9.8"] npm ClojureScript compiler and JS bundler [2:45 AM] So now what I thought was 1 installation turns out to be 4 installations. [2:45 AM] This keeps happening.  It's tiring. Eccentric J  [2:45 AM] You don’t need the clojure library, just the npm module. FHE  [2:45 AM] So the guide is just wrong? Eccentric J  [2:45 AM] No the guide is right FHE  [2:46 AM] "The;v=3 Clojure library which handles all the actual work." not needed? Eccentric J  [2:46 AM] It’s included by the npm module, the clojure library is used more if you’re combining with deps.edn, lein or something like that. FHE  [2:46 AM] Whoops.  I meant to post all of this in the main thread.  Can we move it there? Eccentric J  [2:46 AM] Unfortunately not


Again, sorry for the big post. Thought I was posted all that in this channel all along. Forgot I switched to a private chat 'for a sec'.

eccentric J05:05:58

Have you worked with nodejs before?


Downloading it now. (Yes, I'm actually doing something! Yay!)


automatically install tools, including chocolatey and maybe python and visual studio build tools?


Of course the shadow.cljs guide does not mention whether this is needed during NPM installation

eccentric J05:05:31

With nodejs being one of the most popular languages\ecosystems shadow-cljs is trying to make it convenient by leveraging node\npm’s distribution for new users.


Do I need this stuff?


The line 'Alternatively...install the dependencies yourself' at the bottom is kind of hilarious to me.

eccentric J05:05:28

Yes, will come into play later as you leverage npm modules in your project.


The list of installations just keeps growing....but I'll be grateful all these ones are automatic.


You don’t need it, imo. Native modules is a React Native thing


Ya, like I said, you'll need to install: JVM, Clojure, Leiningen, NodeJS, NPM (I think comes with NodeJS), shadow-cljs


If you need them, you’ll know. It doesn’t hurt to install it though


Being on windows definitely makes a lot of this much harder to setup as well unfortunately.


Sounds like if I don't do it automatically now I might need to manually install a bunch of stuff later. I'm overwhelmed by the amount of things to install already so no to that. lol. I'll just do the auto stuff now I think, even if there's a chance I won't need it.

👍 4
eccentric J06:05:36

That’s true. NPM comes with nodejs. You may not need those tools to get started, but there will be fewer surprises should you branch out to other npm modules.


The installer hasn't mentioned NPM (yet?)


Honestly, I'd default to yes for all optional things. Just in case.

💯 4

and the shadow.cljs installation guide mentions node.js and npm separately


In Windows they like to bundle everything. It’s amazing. In Linux I just grab the one thing I asked for.


Yeah I should really get Linux dual boot going.


Windows doesn't even have a proper command line. Its a huge pain to develop on it. (Haven't tried the new Linux subsystem stuff though)


I hit a roadblock trying to do that on my new-ish laptop a few months ago, though. Windows refuses to give up enough of it's partition's space to allow for a reasonably-sized Linux partition.


So annoying.


I know it seems like you are installing a lot of random things, but essentially you are setting up a JavaScript developer environment AND a ClojureScript one.

eccentric J06:05:34

With shadow-cljs, you can create projects designed for web browsers, node scripts, react native, and npm modules. It also leverages node and npm as distribution. Also, nodejs is a platform to interpret and run JS on your platform (outside of a browser) and npm is a tool to work with packages. Shadow-cljs is available as an npm package.


Also, 'close all open programs for the duration of the installation'. LOOL I have Emacs and command prompt and Hex Chat (for help with Emacs yesterday) and notepad and about 300 Firefox tabs open (including a Discord channel for help with DOOM).


Installer, bro, you're asking a lot. Ha.


Hum, ya, plus I feel you probably don't actually need this. But heck no idea :man-shrugging:


It’s for extending node with native c/c++ code

eccentric J06:05:04

Tools like SASS and other transpiler tools use node-gyp if I recall. It’s good to have.


I was thinking of native modules for react, didn’t even think of node


Welp, my wife has only used 1/3 of the space on this lappy, so I guess I'm doing this. See you again in hopefully just a few minutes...

eccentric J06:05:16

You could just leave things open and see what happens. I doubt it would interfere with those apps.


This laptop is scorching my lap right now because of all the tabs (even with NoScript!). I should at least close Firefox.


Wow. That took a long time

🕑 4

Python was a good chunk of it, but the part that took forever was called 'visualstudio2017-workload-tools'.


Well I went to a command prompt and typed 'npm' to try to see if that was installed somewhere in there and...looks like yes!

eccentric J06:05:15

Great! It’s progress at least.

eccentric J06:05:07

Heading out for the night. The only other requirement may be java, then you should be able to continue the tutorial and start building a web app with reloading and a REPL you can connect cider to. Good luck!


I installed Java (version 8 required for CLJS, yes? newer no good?)


Actually I installed adoptOpenJDK 8. Oracle with their crazy account creation gate demanding all kinds of personal info. Pffft.


Thanks. @jayzawrotny and anyone else who have maybe already left...?


Well, I THINK all that remains for me to install is shadow.cljs


but I see conflicting instructions for that


Well I followed the first instructions at and yes, for some reason creating a project with the npx command shown there somehow gets shadow.cljs installed.

👍 4

The Windows Developer Experience Team is doing an amazing job right now. WSL2 and the new Windows Terminal app are lifesavers for me. WSL2 will get GPU (e.g. ML workloads) and GUI support this year. So you can pretty much never leave the WSL environment.


Currently, I use vcXsrv to run emacs from within WSL, in GUI mode.


This is an FYI for anyone who feels "trapped" in Windows.


I might try it. I guess I would have to install that and then re-install for WSL all of the things I just installed for Windows.


By the way, it's WSL2 now, isn't it? I know very little about it, but I did come across that tidbit somewhere.


Anyway...bedtime. Night! And thanks again all who chimed in to help.


WSL2 is an actual Linux over a hypervisor. It is way better than WSL1. So make sure you are on WSL2.


You can switch any installation between 1 and 2.


Yes you will have to reinstall but it is worth it.


but not between Windows and WSL1/2. I would expect that if so.


OK. good to know.


Why is it worth it?


Worth it if you are used to the Linux way of things. Like me.


Oh. I'm not. ...though I think I will eventually migrate.


Bedtime for me. Have a good night.

👍 4

ahoy! good morning (in CET)


why does let take a vector of alternating symbols and values instead of a map, which is constructed in the same way?


for some reason this bothers me a bit 🙂


it feels like it's using vector with map semantics.


Vector guarantees order

💡 12
Phil Hunt11:05:14

Does anyone have a recommendation on texts (and ideally exercises) to thoroughly understand 'recur' ?

Phil Hunt11:05:16

Something comparable to the recursion chapters in Practical Common Lisp or the Little Schemer?


@phil634 Personally, I found to be extremely good material for learning functional programming. It uses Scheme, and of course Clojure doesn't have tail call optimization right now, but you just mentally substitute calling the function name again for recur. It's so good for learning lisp in general that I read it a few times. It goes over multiple forms of recursion.

Phil Hunt14:05:05

Thanks, but its more the Clojure specific stuff I’m having issues with


Oh I see never mind.


What issues, out of curiosity?

Phil Hunt14:05:54

I think i’ve sorted the specific one, which was making input loop for a turn based game, but it was a bit trial and error

Phil Hunt14:05:29

so I was looking for something that really spelled out what was happening using some examples beyond eg for type loops


Essentially it is just looking for the nearest place it can jump to, and rebinding according to what you pass in.


Other than that, I guess you should know it is looking for loop or fn as jump points, you must pass in the same number of args, and you must be in tail position

Phil Hunt15:05:26

yeah, it was the rebinding bit that was causing me trouble when change was coming from user input

Phil Hunt15:05:10

rather than incrementing or whatever


oh yeah I could see how that might trip you up hehe.

Phil Hunt15:05:24

now i’m onto not understanding state ;)

Phil Hunt15:05:44

I’m trying to port something I wrote in common lisp


Nobody understands state 😛


Oh wow, neat.


I came over from scheme, so I understand that.

Phil Hunt16:05:31

heh, works (kinda)

Manuel Ceron18:05:44

I'm discovering threading macros and loving them because they make some of my code much easier to follow. But I'm concerned about abusing it. So I have a code style question, if I have some code like this:

(-> person
    (assoc :hair-color :gray)
    (update :age inc)
    (cond-> lucky? (assoc :money "a lot!")))

Manuel Ceron18:05:20

Mixing two kinds of threading macros. What do you think about this?

Manuel Ceron18:05:28

Thanks a lot, those two posts are very interesting. He suggests mixing -> and as-> for cases that don't conform. I guess mixing cond-> might be not that bad.


@ceronman Yeah, I will mix -> and cond-> and I do, sometimes, mix -> and ->> or cond->> if I feel it makes the logic easier to read.


Like all "rules", there are times when it's OK to break them.


I think it's fine as long as it is readable. For an example like that, where complexity is minimal, I don't see a problem.


If you think its easier to read, then I'd say go for it. Chances are its easier for others to read as well.


That examples seem fine to me. I'd say the only no/no is changing the thing being chained


Since here you keep modifying person, its easy to follow. We have a person, and we assoc hair color grey, increment age and conditionally assoc money


If you had a get in the middle of it, that would begin to be less readable, and I would break it up into two threads or possibly use as->


(-> (SomeRequest.)
    (.with param1)
    (.with param2)
    (.with param3)
    (->> (mapv inc)
         (filter even?)))


Like in this example, we create a reuqest, make a call, get a response and then process the reponse. I feel its starting to be a lot. So generally I guess my threading macros are either all data transformation on the same logical thing, or all about fetching some data in some nested structure. I'll try not to mix the two, and will try not to change the thing I'm transforming mid-way. If I do, I'll break it up. Like so:

(let [some-request-response (-> (SomeRequest.)
                                (.with param1)
                                (.with param2)
                                (.with param3)
      incremented-even-results (->> some-request-response
                                    (mapv inc)
                                    (filter even?))]


@didibus mapv/`filter` require ->> here


(and in your original example above)


Ah yes true, another reason to break it up 😛, but also I was too focus on trying to have good formatting in slack. Why can't it use a monospace font 😛


But, yes, I agree that having one chain of -> followed by a whole chain of ->> is a very good sign that it should be two separate expressions.


do the clojure CLI allow you to create a deps.edn project ?, e.g. clojure make-me-a-new-app and it creates the directory structure, deps.edn file etc ?


He's using that already.


See his next message.


Oh, assuming the error is not that the alias doesn't exist. Can you paste us the error?


Execution error (FileNotFoundException) at .FileInputStream/open0 (
app (No such file or directory)

Full report at:
I thought it would just work out the box, I didn't realise


I need to setup the functionality! Thanks, I'll check out the link you pasted


I thought it was clojure -A:new app namebut that is jujst genereating an error message i dont understand


The argument that Stuart Sierra makes around that is a good one: -> tends to indicate threading an important "entity" or "collection" as the "subject" because that's how non-sequence Clojure functions work. Then ->> indicates threading sequences -- the last argument position.


Yes @qmstuart clj-new will generate a new project with deps.edn -- what is the error message you get?


Yes, the only time I find I need to mix a lot of -> and ->> is when manipulating strings, because those functions are inconsistent in where they take the argument. I think that's really the only place where I tend to be okay with mixing them heavilly


@qmstuart You should also see a message like this if you don't have the alias set up:

WARNING: Specified aliases are undeclared: [:new]


Without that alias, clojure will treat arguments as the names of scripts to load and run (so it sees app and tries to load and run a file called app as Clojure code).


Hence the No such file or directory error.


I've been so spoiled by the tooling working in MS/C# land


I don't know if this is any consolation, but I used to be a C# dev at a microsoft shop, an what I can say is at first I thought the same, but once you understand the linux/jvm/clojure tools, they become much easier to debug and build on top, where as with the C# tooling if the GUIs are failing you, it becomes really hard to root cause, and the lack of command line for most of them is hard to automate. At least it was a few years ago.


Which I think explains why Windows never gained traction with developers, and why Azure windows is a big failure, and Microsoft is basiclly porting linux to windows now, and porting C# to linux.


I think you'll find far more developers around the world have always used Windows @didibus ... What you said is fairly common from Linux people tho' 🙂


I don't mean using Windows, I mean running servers on it.


The data from Azure show that Windows is the least popular platform for that


Ah, right. Deployment vs development.


That's why Microsoft has this new embrace Linux strategy 😛, because Azure is their new cash cow. I like Windows as a user OS, though yes I did switch to Linux 😛. Mostly because I find for non Microsoft dev work, no one targets windows, and to be honest, the terminals and shells on windows is a mess in my opinion.


I switched to linux recently from WIndows as my home OS. The learning curve is steep


Yes, it can seem pretty overwhelming. I like how Windows 10 has WSL so you can use Windows for a lot of stuff but still use Linux for command-line stuff on the same machine.


(which is like macOS since System X arrived)


Ya, it took me a while for sure. But once things click its pretty nice. When thigns are broken, you can often fix it. In Windows, you have to re-install the OS, or good luck fixing a broken registry.


Interestingly enough, macOS is my least favorite OS. I've yet to try WSL, I will eventually, but I'm waiting for it to stabilize I guess. I'm confused with the whole 1 to 2.


Happy to answers about WSL 1/2 if you want. DM me, or ping me in the #windows channel.

👍 4

You might find it helpful to start with this deps.edn file


where I install the IDE, File > New Project and all of this taken care off 🙂


Hopefully clojure will get to that point eventually


That would go in your ~/.clojure folder (overwriting the default one -- if you haven't changed that file, otherwise you'll want to just read my dot-clojure file and add parts of it into yours).


Clojure expects you to work with command-line tools, to be honest.


Ya, I'd say Clojure follows pretty closely with the Unix philosophy of leveraging config files and simple command lines tools that compose


@didibus, @seancorfield thank you! That's it working now 🙂


I have a project that I am trying to cider-jack-in to, and it's failing due to what appears to be nrepl looking for a package version and not finding it... for a package that has nothing to do with the project I'm in.


it's baffling.


@patrickanium Can you share the error messages?


[nREPL] Starting server via /Users/foo/bin/lein update-in :dependencies conj \[nrepl\ \"0.6.0\"\] -- update-in :plugins conj \[refactor-nrepl\ \"2.5.0-SNAPSHOT\
   \"\] -- update-in :plugins conj \[cider/cider-nrepl\ \"0.24.0\"\] -- repl :headless :host localhost
 21error in process sentinel: nrepl-server-sentinel: Could not start nREPL server: If there are a lot of uncached dependencies this might take a while ...
 22Downloading: origami/origami/maven-metadata.xml from 
 23Downloading: origami/origami/maven-metadata.xml from 
 24Downloading: origami/origami/4.3.0-7/origami-4.3.0-7.pom from 
 25Downloading: origami/origami/4.3.0-7/origami-4.3.0-7.jar from 
 26java.lang.IllegalArgumentException: Provided artifact is missing a version: [origami/origami nil]


but that package is never mentioned in the project.clj


What's in your ~/.lein/profiles.clj file?


;; put this into profiles.clj in ~/.lein folder
{:user  {:jvm-opts ^:replace ["-Xmx3G"]
         :plugins [
                   ;; [cider/cider-nrepl "0.21.1"]
                   [cider/cider-nrepl "0.24.0"]
                   ;; [lein-ancient "0.6.15"]
                   ;; [jonase/eastwood "0.3.3"]
                   [lein-pprint "1.2.0"]
                   [lein-try "0.4.3"]
                   ;; [lein-cloverage "1.0.13"]
                   [refactor-nrepl "2.5.0"]
         :middleware [cider-nrepl.plugin/middleware
                      ;; refactor-nrepl.plugin/middleware
         :dependencies [
                        ;; [nrepl "0.6.0"]
                        [nrepl "0.7.0"]
                        ;;[org.clojure/tools.namespace "0.2.11"]



(if you spot anything else wrong in the profiles.clj, lemme know!)


There shouldn’t really be anything related to cider in there


I had installed the origami/origami thing when messing around with another project.


ah, ok... so, take the cider things out?


All the middleware stuff, cider stuff, and nrepl stuff you can throw away


;; put this into profiles.clj in ~/.lein folder
{:user  {:jvm-opts ^:replace ["-Xmx3G"]
         :plugins [
                   ;; [lein-ancient "0.6.15"]
                   ;; [jonase/eastwood "0.3.3"]
                   [lein-pprint "1.2.0"]
                   [lein-try "0.4.3"]
                   ;; [lein-cloverage "1.0.13"]
         :dependencies [
                        ;;[org.clojure/tools.namespace "0.2.11"]



If you jack in CIDER ensures that stuff is injected. If you’re starting your project yourself you should ensure that stuff is present in your project. Profiles are just the source of frustration and forgotten deps


ah ok... would it also mean, if you put stuff in the project, it's more portable for others to use?


{:user  {:jvm-opts ^:replace ["-Xmx3G"]
         :plugins [[lein-pprint "1.2.0"]
                   [lein-try "0.4.3"]]
         :dependencies []}}



What’s the (cider-required-middleware-version) form?


a desperate late night troubleshooting session, I'm sure.


removing that, too.


{:user  {:jvm-opts ^:replace ["-Xmx3G"]
         :plugins [[lein-pprint "1.2.0"]
                   [lein-try "0.4.3"]]
         :dependencies []}}


Can you rename the file so nothing is effectively there and try this whole process again?


Nearly all Leiningen-related problems are caused by random stuff in ~/.lein/profiles.clj




gotcha... renamed it, cider-jack-in produces the same origami/origami error as before.


but feeling good about cleaning up profiles.clj!


Ok. So now we know the error is localized to your project and not your computer


Can you run “lein repl” from a command line? Let’s remove all (mostly) tooling and see if it starts?


lein repl
If there are a lot of uncached dependencies this might take a while ...
Provided artifact is missing a version: [origami/origami nil]


So the project is broken. Now try “lein deps :tree”


that just returns the aforementioned error... this time in the terminal

java.lang.IllegalArgumentException: Provided artifact is missing a version: [origami/origami nil]
 at cemerick.pomegranate.aether$add_version_from_managed_coord.invokeStatic (aether.clj:654)
    cemerick.pomegranate.aether$add_version_from_managed_coord.invoke (aether.clj:646)
    cemerick.pomegranate.aether$add_version_from_managed_coords_if_missing.invokeStatic (aether.clj:682)
    cemerick.pomegranate.aether$add_version_from_managed_coords_if_missing.invoke (aether.clj:676)
    clojure.core$partial$fn__5824.invoke (core.clj:2624)
    clojure.core$map$fn__5851.invoke (core.clj:2753)
    clojure.lang.LazySeq.sval (
    clojure.lang.LazySeq.seq (
    clojure.lang.ChunkedCons.chunkedNext (


I have a hodge-podge poorly understood repl/nrepl/cider/emacs setup, as a side note (on par with my profiles.clj), fyi.


I once downloaded and attempted to run which is all I know about origami...


I almost feel like lein is climbing up out of my project directory and trying to install things from other projects.


Are you sure you are in the right directories?


let me check.


We shouldn’t be in emacs at all


I'm not at this point...


Just do the command line. Emacs will just invoke commands that we can invoke ourselves but much more difficult to see which directory we are in and the errors


in tmux/terminal.


I'm isolating a copy of the project directory elsewhere in my filesystem and will use a fresh terminal instance on it; stand by.


whoa. cp -r'd the project to my desktop, opened a fresh terminal... ran lein repl, and same error! I checked project.clj and no mention of origami in there...


(defproject testproject "0.1.0-SNAPSHOT"
  :description "an example"
  :min-lein-version "2.0.0"

  :plugins [[duct/lein-duct "0.12.1"]
            [lein-tools-deps "0.4.5"]]

  :lein-tools-deps/config {:config-files [:install :user :project]
                           :aliases      [:backend :dev :test]}

  :resource-paths ["resources" "target/resources"]
  :middleware     [lein-duct.plugin/middleware

  :target-path    "target/%s/"
  :main           ^:skip-aot testproject.todo-example.backend.core

  {;; generated by duct
   :dev          [:project/dev :profiles/dev]
   :repl         {:repl-options {:init-ns user}}
   :uberjar      {:aot :all}
   :profiles/dev {}
   :project/dev  {:source-paths   ["dev/src"]
                  :resource-paths ["dev/resources" "target/dev/resources"]
                  :target-path    "target/dev/"
                  :dependencies   [[integrant/repl "0.3.1"]
                                   [eftest "0.5.4"]
                                   [kerodon "0.9.0"]
                                   [com.gfredericks/test.chuck "0.2.7"]
                                   [reifyhealth/specmonstah "2.0.0"]
                                   [test2junit "1.4.2"]]
                  :plugins        [[test2junit "1.4.2"]]

                  :test2junit-output-dir ".out/test-results"}

   :local-staging {:target-path    "target/local-staging/"
                   :resource-paths ["dev/resources" "frontend-target/local-staging"]}
   :staging       {:target-path            "target/staging/"
                   :resource-paths         ["dev/resources" "frontend-target/staging"]
                   :lein-tools-deps/config {:aliases ^:replace [:backend]}}
   :prod          {:target-path            "target/prod/"
                   :resource-paths         ["frontend-target/prod"]
                   :lein-tools-deps/config {:aliases ^:replace [:backend]}}

   :test {:resource-paths         ["dev/resources" "frontend-target/test"]
          :lein-tools-deps/config {:aliases [:test]}}})


I'm going to generate a new project with a lein template and see if this happens in it.


lein repl in that via terminal worked fine.


ok, renamed .m2 and ran lein repl in the root of the problem project and I see every single dependency ever there downloading.


I would assume it would only attempt to install dependencies for this project.


I wonder if there is something in the project.clj above that is making that happen.


I removed .m2 and ran lein repl from my newly generated lein template app, and it only installed the .m2 deps for that project... so there's something up with my project.clj above... or something it invokes.


I'll just start commenting things out.


At a guess: one of the dep's deps is screwy. You might be able to define origami at a top level instead to overwrite it


found the source of the problem:

[lein-tools-deps "0.4.5"]


For testing purposes, try adding [origami "4.3.0-7"] to your deps


Is Ring and Compojure the standard clojure way of creating a web server / web API?


or should I be looking at something else?


I just want a simple server that can respond to POSTS and GETS


Then that's a good pick

👍 4

In Microsoft land, I can use SignalR to send data from back end to front end to save polling, is their an equivalent library that does this for Clojure?


So you want to spin up a websocket, basically?


Or are you wanting something more involved?


Eventually, I want to have a front-end that will update when the back-end sends a message, where the back-end is pulling messages of a rabbitmq queue


but also want hte back end to be able to respond to HTTP GETS / POSTS as well


I'm more asking: are you wanting to implement the updates yourself, or are you wanting a full framework that does the synchronisation for you?


If you want a simple thing where you write the notifications yourself, you can make a websocket endpoint. Your frontend connects to that, and reads from that


It's custom, but you have to implement stuff yourself


As for full framework, there's probably something out there that does it


looks like http-kit can do it I'll look into this.


is pulling in everything I've ever installed in .m2... I have a deps.edn in my project but not anywhere else... am I supposed to have a higher level one?


Maybe there's something strange in your deps.edn file that is causing that?


That is only going to have a default Clojure version in it and the "standard" repository definitions.


{:paths ["src"]
 :deps  {org.clojure/clojure              {:mvn/version "1.10.1"}
         org.clojure/clojurescript        {:mvn/version "1.10.520"}
         com.cognitect/transit-cljs       {:mvn/version "0.8.243"}
         com.taoensso/timbre              {:mvn/version "4.10.0"}
         integrant                        {:mvn/version "0.8.0-alpha2"}
         funcool/bide                     {:mvn/version "1.6.0"}
         medley                           {:mvn/version "1.3.0"}
         metosin/reitit-spec              {:mvn/version "0.3.7"}}

 {:dev        {:extra-deps {cider/cider-nrepl {:mvn/version "0.21.0"}
                            refactor-nrepl    {:mvn/version "2.4.0"}}}
  :test       {:extra-deps {com.gfredericks/test.chuck {:mvn/version "0.2.7"}
                            eftest                     {:mvn/version "0.5.4"}
                            kerodon                    {:mvn/version "0.9.0"}
                            reifyhealth/specmonstah    {:mvn/version "2.0.0"}
                            test2junit                 {:mvn/version "1.4.2"}}}
  :backend    {:extra-deps {bk/ring-gzip             {:mvn/version "0.3.0"}
                            com.datomic/datomic-free {:mvn/version "0.9.5697" :exclusions []}
                            duct/core                {:mvn/version "0.7.0"}
                            duct/module.logging      {:mvn/version "0.4.0"}
                            duct/module.web          {:mvn/version "0.7.0"}
                            liberator                {:mvn/version "0.15.3"}
                            environ                  {:mvn/version "1.1.0"}
                            org.yaml/snakeyaml       {:mvn/version "1.23"}
                            org.flatland/ordered     {:mvn/version "1.5.7"}
                            ring                     {:mvn/version "1.7.1"
                                                      :exclusions  [org.clojure/tools.namespace]}}}
  :cljs       {:extra-deps {re-frame                         {:mvn/version "0.10.6"}
                            reagent                          {:mvn/version "0.9.0-rc3"}
                            thheller/shadow-cljs             {:mvn/version "2.8.60"}}}
  :cljs-dev   {:extra-deps {binaryage/devtools         {:mvn/version "0.9.4"}
                   {:mvn/version "0.4.5"}}}
  :cljs-local {}}}


My experience is that trying to blend lein (or boot) with deps.edn is an exercise in frustration. Either stick to lein and project.clj or switch completely to the Clojure CLI and deps.edn


I wrote boot-tools-deps to attempt that and it never worked properly beyond the very simplest deps.edn files so I archived it. I don't know how well lein-tools-deps works but I really wouldn't recommend attempting this sort of thing...


(`lein` already does enough "magic" on its own, without trying to override how it resolves dependencies using a library with different algorithm for resolving conflicts)


gotcha... this is an existing project I'm exploring... so I'll have to possibly just pull it all into project.clj.


what does this error mean?:


Uncaught Error: Vector's key for assoc must be a number.

eccentric J23:05:37

That means you're running code like (assoc [] :my-key "hi") where assoc only works on vectors if key is a number referring to its index like (assoc [1 2 3] 1 :x) ; => [1 :x 3]


it's giving an error for this code, where I'm deep merging two maps. It has worked so far for merging maps, but not for the latest pair of maps that I'm inputting as parameters:

(defn deep-merge
  "Recursively merges maps."
  [& maps]
  (prn "" (count maps))
  (prn "maps in deep merge are " maps)
  (letfn [(m [& xs]
            (if (some #(and (map? %) (not (record? %))) xs)
              (apply merge-with m xs)
              (last xs)))]
    (reduce m maps)))


specifically giving the error on the last line with the reduce

eccentric J23:05:52

Would (merge-with into map1 map2 ... mapn) not cut it for your use case?


(merge-with into {:foo 6} {:foo 4 })
Error: 4 is not ISeqable
    at Object.cljs$core$seq [as seq] ()
    at Function.eval [as cljs$core$IFn$_invoke$arity$3] ()
    at Function.eval [as cljs$core$IFn$_invoke$arity$3] ()
    at Function.eval [as cljs$core$IFn$_invoke$arity$2] ()
    at eval ()
    at merge_entry ()
    at eval ()
    at Function.eval [as cljs$core$IFn$_invoke$arity$3] ()
    at Object.eval [as cljs$core$IReduce$_reduce$arity$3] ()
    at Function.eval [as cljs$core$IFn$_invoke$arity$3] ()


so what's happening is that with deep-merge it's recursing down these maps, but also down the vectors, and that's what's causing the error, correct?


so maybe using (vector?)

eccentric J23:05:59

I'm cleaning up a version of the function I've been using. Instead of map or vector I've been using (coll?) and when it's a coll I use into since it works for appending to whichever source collection type.


okay I mis-diagnosed the issue earlier:

=> (deep-merge {:foo [4 5 6]} {:foo [7 8 9]})
"" 2
"maps in deep merge are " ({:foo [4 5 6]} {:foo [7 8 9]})
{:foo [7 8 9]}



(defn deep-merge
  "Recursively merges maps."
  [& maps]
  (prn "" (count maps))
  (prn "maps in deep merge are " maps)
  (letfn [(m [& xs]
            (if (some #(and (map? %) (not (record? %))) xs)
              (apply merge-with m xs)
              (last xs)))]
    (reduce m maps)))


the actual maps are so big that it's harder to debug

eccentric J00:05:56

Might take some modification to fine-tune

(ns app.merge-deep)

(declare smarter-into)

(defn merge-deep
  [& maps]
  (->> maps
       (reduce #(merge-with smarter-into %1 %2))))

(defn smarter-into
  [prev next]
      (and (sequential? prev)
           (sequential? next)) (into prev next)
      (and (coll? prev)
           (coll? next)) (merge-with smarter-into prev next)
      :else              next)
    (catch Exception e
      (println "Could not merge values" {:prev prev
                                         :next next})

  (merge-deep {:a {:b {:c [1]}}}
              {:a {:b {:c [2]}}}))
;; => {:a {:b {:c [1 2]}}}


this works:


copied from somewhere on GitHub:

(defn deep-merge [& maps]
  (apply merge-with (fn [& args]
                      (if (every? map? args)
                        (apply deep-merge args)
                        (last args)))

eccentric J00:05:00

Depends what you want it to do when vectors\lists are encountered. This version will use the right most val mine concacts the vectors\lists but if that's all you need it makes sense.

eccentric J00:05:52

The try and catch in mine is not necessary either, I just put that in to help debug any specific values it can't merge and if it does fail, it just takes the right-most value to make it a little safer.


I just followed the 'Installation" section of and there are a few things I don't understand...


1. Why does that guide mention needing Node.JS and NPM? Someone in the chat here mentioned Node.JS should come with NPM so after I installed Node.JS I checked (command prompt, 'npm, got a response).

eccentric J00:05:08

Yes, node comes with npm but there are ways to install it that may not include both packages. npm is required to download the shadow-cljs package and install it into the local directory node.js is the runtime to execute it


I have a feeling that in the early days of node, installing it did not install npm at that time?