Fork me on GitHub

humm you are making me curious. gona dig it for a couple hours 🙂


There's a #chlorine channel if you need any assistance with that (we have channels for pretty much everything here!).


perhaps one day you can share a little bit about your work? where do you use clojure?


World Singles Networks -- online dating.


humm sounds interesting 🙂 gona search that too


We started with Clojure 1.3 and took an alpha build to production about nine years ago. It's been interesting to watch the Clojure ecosystem evolve during that time.


Nowadays, we use the official CLI with deps.edn for everything. I think Brave & True talks about Leiningen (and I'll bet that finance book does too).


that’s a lot of time yes! So do you guys use clojure only for everything? I ask this because some use also cljs to devel frontend but other (i thinks matabase guys not).


When we started building our front end, ClojureScript was still pretty rough around the edges and the tooling was... limited... so we went with React.js for the front end. But all of our back end is Clojure.


yes they use Lein but I think I can do the basics with both. in fact I have a custom repl setup to work with both of them


any plans to move or it just works? (the frontend)


It works, it would be a huge amount of work to migrate, and our JS devs use a fairly FP style approach anyway.


We may look at cljs for new front end projects at some point.


that would be my question if you didn’t write it.


so my interest in clojure is not frontend in particular but to learn how to code simple parsing scripts; some calculations; web scrappers too.


Is it important in which order -J and -i options are passed to clojure?


I am starting a repl.server with something like

-J-Dclojure.server.repl={:address \"\" :port 5555 :accept path-to-accept/accept-fn} 
-i "path-to-init-file"


and if I switch the -i and -J option I get an error


The documentation you should see when you type clojure --help documents that the order is significant.


Well, at least the format of the command line shows categories of options in a particular order, which strongly implies those kinds of options must be in that order.


That help output shows this line: Usage: clojure [dep-opt*] [--] [init-opt*] [main-opt] [arg*] where -J is one of many kinds of dep-opt, and -i is one of several kinds of init-opt.


Isn't Atom pretty much dead by this point? And VSCode being the semi-official successor?

Edward Hughes11:03:04

It would be the first I've heard of it. A lot of people seem to prefer it over the Emacs experience.

Edward Hughes12:03:12

I recommend it as the "Intro to Clojure" editor because it's easy to set up and the keybinds for working at the REPL are less... expansive than in Intellij.


VSCode + Calva should also be very easy to set up. Not sure how the keybindings compare, though.


Yesterday night I installed and configured Atom/Chlorine + parinfer + clj-kondo in 20mins. Got very impressed positively.


I mean there is practically no dev activity anymore for the Atom editor, also Github stopped supporting it with money and dev time since they got taken over by Microsoft


Atom is a solid editor and all the packages I use seem to get regular updates so maybe it's like all those Clojure libraries out there that are "complete" and get almost no dev activity? 😉


I would only switch to VS Code if it had a version of Chlorine available -- pure socket REPL, no dependencies needed at all.

👍 8

I think it might have Chlorine.


Clover is Chlorine?


well it's developed by mauricioszabo as chlorine


Chlorine is really two parts: the Atom integration (Chlorine itself) and the underlying repl-tooling library (which is portable). Clover is built on repl-tooling in the same way: VS Code integration (Clover) and the same underlying repl-tooling library. In theory, any editor that can run JS can run repl-tooling and therefore get a Chlorine-like integration.


OK so no matter which one I pick, for the enduser (newbie developer) the experience should be the same?!


I just asked Mauricio about this and you'd want some sort of structural editing assistance (parinfer, paredit) in VS Code as well as Clover. In Atom, those are both packages you can install (separate to Chlorine). Not sure what exists in VS Code for that but Calva includes at least some of that -- and Calva has its own evaluation support but relies on nREPL. So to have the same experience in VS Code you'd probably need Calva installed anyway. It depends what part of "the experience" you're referring to.


I haven't spent any time trying to set VS Code up "properly". There is a standalone paredit package for it (I just looked). There's also a standalone parinfer package too.


Atom doesn't have an up to date package for dealing with nREPL (ProtoREPL supported nREPL but it is no longer maintained) and most people still use nREPL rather than a bare socket REPL. I just prefer the latter so I don't need any additional dependencies in my setup.


@U3NP9AM0S I am biased, naturally, but I would say that Calva is about as easy and quick you can get up and running with a Clojure dev environment today. It doesn't take a minute if you have the Clojure dependencies in place. It is actively developed and maintained, and we try to be responsive giving support.


(sorry the delay, I was driving home) @U04V70XH6 @U0ETXRFEW I see the advantages of not installing deps to work with REPL but in my case I am too n00b to make such decisions 🙂 in fact my decision will be “does it support Parinfer?!” 🙂 Ok seriously; later today I am going to test VSCode with Calve and decide, but yes anything that helps me gasp with parentheses and ‘autocomplete’ is a must have.


@U3NP9AM0S If you insist with Parinfer you need to disable Calva's autoformatter:


But I'd say that Paredit helps you gasp with the parens too:


so I must check peredit. I though only parinfer did those magic tricks


Parinfer is quite a bit more magic, but I think the basic Paredit commands are easy enough to get started with and it helps ”get” the s-expressions very hands on.


is Paredit maintained outside of Calva?


ah and I see Calva supports clj-kondo too, nice


Paredit is maintained and shipped together with Calva. It relies on infrastructure used by a lot of Calva functionality.


awesome! I think this is nice because often I see too much moving parts and it’s inevitable that some get forgotten in time.


The clj-kondo extension installs automatically when Calva is installed.


I think I’ve installed it via homebrew


yep - let’s see if it does not collide


The clj-kondo extension brings its own clj-kondo jar, but it doesn't hurt having a brew install as well, b/c nice to have separate from vscode.


ah ok seem legit. well gona dig this now 🙂 will be back later with everything working 🙂


And #calva-dev is a good place to get help using both Calva and the clj-kondo extension.


😅 let me jump into. 10x for everything by the way


Can we run an arbitrary function in an alias of Clojure CLI? So far I am seeing examples for running the main function of a namespace.


@hindol.adhya Yes, but it's likely you'll need the Corfield comma:

$ clojure -Sdeps '{:aliases {:foo {:main-opts ["-e" "(+,1,2,3)"]}}}' -A:foo


Why is it called the Corfield comma? 😀


Because Sean Corfield invented that solution

Alex Miller (Clojure team)14:03:34

there are several options for doing this - you can use -e to run arbitrary expressions (`requiring-resolve` can be handy), or -m to run a namespace with a -main, or just pass the name of a .clj file to load and run (can do anything you want)

Cas Shun14:03:30

Hello, I have some large data (converted to a map) that I need to "browse" so I can figure out what to do with it. What are some workflows I can utilize for working with large data structures?


There are a few methods I might try. One approach is to just spit ting to a file and interrogating using shell tools. So, if you're happy with looking at json (and your map can be converted to json easily) you could use something like cheshire/jsonista to convert to json and write to file - then pipe through something like jq to format. Or even just open the file in a browser which has a collapsible json explorer plugin. I'm not aware of any interactive hierarchical edn viewer. I've also found eq a useful jq-lite for edn (


Alternatively you could start interrogating your data directly from the REPL. If you're unfamiliar with the format of the data, you could use functions like keys, first , select-keys, get, get-in to help narrow down the data.

👍 4
Cas Shun15:03:11

I feel like trying to navigate with functions would take a while since it's a deeply nested structure

Cas Shun15:03:55

I'll try the json method for now, unless something better comes up, thank you


I haven’t tried this yet, but maybe this could help?


Hmm that does look interesting.

Cas Shun16:03:32

cool, thanks


I find Clojure's datafy and nav my go-to tools for exploring large datastructures. One such tool is REBL, but more recently I have switched to using shadow-cljs Inspect (even for browsing JVM data). •


Sorry, my post was confusing. I don't want to evaluate an expression. I want to call a function that is not -main. @borkdude @alexmiller

Alex Miller (Clojure team)16:03:27

then probably -e is your best bet to run any arbitrary expressions

Sy Borg17:03:46

can anyone please provide an example of flattening a sequence without using flatten (`tree-seq`), but with recursion?


(defn flatten* [x]
   (if-let [x' (first x)]
     ((if (sequential? x') concat cons) x' (flatten* (rest x)))



(defn flatten* [x]
   (if-let [x' (first x)]
     (if (sequential? x')
       (concat (flatten* x') (flatten* (rest x)))
       (cons x (flatten* (rest x))))
to have almost the same behavior as flatten

Sy Borg17:03:13

thanks, but the 1st version doesn't work as expected (doesn't pass the test), and the 2nd one causes StackOverflow

Sy Borg17:03:27

I'd like some recur version


Can you share a test case?

Sy Borg17:03:51

(deftest five-level-nesting
  (testing "5 level nested list"
    (is (= [0 2 2 3 8 100 4 50 -2]
           (flatten-array/flatten [0 2 [[2 3] 8 100 4 [[[50]]]] -2])))))


Sorry, did typo. Try second example again. It should work now

Sy Borg17:03:54

no, unfortunately, tested on

(def s [2 [1 3] 9 [4 [5 6 [7]]] 8])


         (if (seq sq)
           (if (sequential? (first sq))
             (concat (fl (first sq)) (fl (rest sq)))
             (cons (first sq) (fl (rest sq))))))]
  (fl [2 [1 3] 9 [4 [5 6 [7]]] 8]))

Mario C.19:03:38

(defn flatten*
   (flatten* col '()))
  ([col ls]
   (loop [cl col
          r ls]
     (if (empty? cl)
       (if (not (or (seq? (first cl))
                    (sequential? (first cl))))
         (recur (rest cl) (conj r (first cl)))
         (recur (rest cl) (flatten* (first cl) r)))))))

Mario C.19:03:47

@U6G4QKULA Its a mixture of looping/recursion :man-shrugging:

Sy Borg20:03:19

thanks, guys


The last version above flatten* has a small mistake causing the order to be reversed. It is fixed by just changing

   (flatten* col '()))
   (flatten* col []))
so that the conj appends to the end.


Rather than recursion or looping I'd prefer to use pure laziness.

(defn lazy-flatten [coll]
    (when-let [xs (seq coll)]
      (let [x (first xs)
            n (next xs)]
         (if (sequential? x)
          (concat (lazy-flatten x) (lazy-flatten n))
          (cons x (lazy-flatten n)))))))