Fork me on GitHub
Drew Verlee12:09:47

Is it recommended to name function params after their types? (m)ap, (v)ector, etc..? Like if there is a function (person/lookup …) defined as (defn lookup [???] …) would it make sense to have the param be name or m?


for more generic code, I think it is idiomatic to use m for map and v for vector, etc. If this particular map has, for instance, only :first-name and :last-name keys, and the function will not be used in more generic settings, then calling it name could be more idiomatic. /my two cents


I created a simple macro to write (f (+ 44 55) (+ 44 66)) as (verbosely! f (+ 44 55) (+ 44 66)), and


then I get logs:

Calling: (f (+ 44 55) (+ 44 66))
With: 99 110
Returns: 209


what tools do you use to debug your code?


I use a REPL and that's it


I make sure that the code I'm writing or using is amenable to REPL exploration


avoid mutable state, make sure things pass data and not objects, avoid long call chains A -> B -> C


any video related? I'd like to see it in action


not familiar with such tools actually, I barely used REPL for debugging before


by the way, it's Clojure or ClojureScript?


Who here is interested in mob programming on open source together?


What is mob programming?


One computer (one person driving the computer). Everyone else navigating, researching, discussing how the code should be.


I'm interested in giving it a go but don't know any clojure devs as I'm on the island of Australia where we are about the last country to adopt any decent tech or even get it.

Drew Verlee14:09:01

The morning paper talked about a pair programming Study. The outcome made it sound like pairing was a slight advantage in many scenarios. However, to me it hinted that it would have huge payoffs in longer projects where people would be more familiar with the entire project by having paired more often. Basically, if its foreseeable that you will be touching that system in the foreseeable future, you might as well be their for most of the building of it. Otherwise, you confine your team to silos and hope no one gets sick or needs help -_-.


@drewverlee sorry I didn't quite get what your conclusion was there

Drew Verlee14:09:36

@grounded_sage That pair programming and by extension mob programming, imo, is a valid approach. The study showed that solutions that resulted from the paired teams were half the code as the solo approaches. Which to me means a “mobbed” solution would be much less complex on average then a solo one. It also means the mob would understand the whole code base, which would show huge benefits when it came time for a refactor. I need to watch the video to comment on it specifically, which i should have before i commented.


Cool. Yea these are my conclusions as well. You also have the benefit of the team mentality. The best sports teams aren't the ones that assemble the best players. Instead it is the ones that play the best together.


Also just thinking at a higher perspective. You are always trying to write code for a future version of yourself or another person entirely. To a certain degree the more people you have contributing at the time of input. Then the more likely the code will be readable and understandable by others and your future self.


Which would reduce refactoring and chances of bugs. Significantly in my mind.

Drew Verlee15:09:58

Like most things, you can create “teams” but often times the borders dont make sense. Ops and Devs is a good example of a bad divide. Front and Back might be a good one, just because the goal might be significantly different and the contract very well defined. Its like building abstractions, if contract between two things has to change when one changes then maybe the belong “together”.

Drew Verlee15:09:28

Sorry, just explaining somethings to myself as were talking about them. Not trying to preach 🙂


Yea I got a bit lost there with what you said but I think I got what you were conveying


I like what is said in the talk. If you aren't learning or contributing to the team. Don't feel obliged to be there. The team should be dynamic and fluid.


Even if there is merely being present with the team. Not necessarily in a separate room.


I'm really interested in finding others who want to experiment with this approach. Perhaps by working on open source.


hit me up


only issue is the screensharing tho


well I'm not available ATM for a peer session, but if you have the willingness to do the minimum viable amount of organization to make this happen, count me in


would be neat to have some kind of twitch, but with instead of awful video


old school screensharing is SSH on the same box and use screen or tmux 🙂 but no IntelliJ or cursive 😛

Drew Verlee15:09:38

I’m very ready to jump into an open Source Project in Clojure. Im actively searching for a good fit for me. I have considered A) Something related to Onyx B) boot ported to node I would also be willing to try a mob pair programming approach.


my "hack of the week" project is to reproduce in clojure. i aim to call it 🙂


I could completely push what I have (some scaffolding and a bunch of routes) and well, if you're interested it's pretty easy to jump in I imagine


how about some teamspeak for mob peering ?


(fyi I'm not available right away, gotta work for the next couple hours


That's alright guys I have some things on over the next several days. But I am super stoked to have found some people keen on this. We shall all chat sometime soon about what time suits best for everyone. Yay!


aaright, talk to you then :thumbsup:

Drew Verlee16:09:43

I'll take a look at the project @U716Q56R2


I just wanted to jump in here and say that I'm also interested in participating in something like this


Maybe it wouldn't be a bad idea to create a channel for this? #mob-programming or #pair-programming or something


fresh souls ! 😋


#mob-programming is open for business


@drewverlee Boot ported to Node sounds like an interesting project I could get behind.

Drew Verlee22:09:42

There is a Google summer of code for it. @grounded_sage , I'll link the doc when I find a minute.


is there an easy way to compare two maps when one gets returned from a function and one is a regular map?


@alexkeyes in clojure maps (and most things) are simple data, so you can just compare them with the = function, regardless of where they came from


@bfabry so the right kind of syntax to compare would be something like `(= (function-that-returns-a-map arg) (:crazy huge :map with :info in :it))?


yes! except the delimeters for a map are {} so it would be (= (map-returning-fn arg) {:map values :go here}) 🙂


you can also get a pretty reasonable diff using ( first-map second-map)


awesome thanks for the help!


one more follow up question: the map I need to compare my function too is pretty large and unsightly, it’s valid to put it in a (def big-map {crazy huge :map with :info in :it}) right?


yup. that stores the map in a var named big-map and wherever you use that var clojure will replace it with the value stored


okay awesome thanks for answering my questions! It’s great being able to have a place to ask questions like this I know are simple but I’m not 100% on.


no worries. btw if you're just starting out I'd recommend working through the "Clojure for the Brave and True" online/print book


yep I have that sitting here on my desk. I’ve also gone through living clojure and honestly I have a bit of a preference for that since it provides examples and challenges on a per concept basis, instead of at the end of a chapter


nice. I've never actually read living clojure


also, feel free to play around in the repl. try things out like (= {:a 1 :b2} {:a 1 :b 2}). the repl is a great place to explore and prod things and is a great separator from other languages that are more "compile and run main" types of languages


this also get's folks up on the basics pretty quick:


breaking out of the ‘save then run’ mentality is definitely something I want to work on. It’s really cool how powerful the REPL is


also, @john another cool point of living clojure is they have a series of daily 4clojure programming exercises to get done with a reference to each section the problem deals with


do you guys have recommendations for actual classes I might be able to take, aside from reading books or writing code?


There’s also Eric Normand’s videos at


well, writing code will be the most effective thing you can do. after that books. tbaldridge has really excellent videos if you are a video person


at the conjs that happen every year (they are going to just one per year next year) there are classes for beginners


okay all good


There might be some other classes out there with a similar format. Keep tabs on the Cognitect team. Sometimes they give classes on various subjects at various locations.

Alex Miller (Clojure team)17:09:12

There will be an intro class before the conj taught by Carin Meier


I'm building a bidi routes map. All works fine until I want to limit one of the routes to :get requests (according to Here are variations that all work, but without the guard clause:

(defn- routes []
  ["/" {"" (-> start-page (tag :index))
        "login" (-> login-page (tag :login))}])

(defn- routes []
  ["/" {"" (-> start-page (tag :index))
        "login" {"" (-> login-page (tag :login))}}])

(defn- routes []
  ["/" [["" (-> start-page (tag :index))]
        ["login" (-> login-page (tag :login))]]])

(defn- routes []
  ["/" [["" (-> start-page (tag :index))]
        ["login" [["" (-> login-page (tag :login))]]]]])
Here are variations with a guard clause that I've tried but that DO NOT work:
(defn- routes []
  ["/" {"" (-> start-page (tag :index))
        "login" {:get (-> login-page (tag :login))}}])

(defn- routes []
  ["/" {"" (-> start-page (tag :index))
        "login" {:get {"" (-> login-page (tag :login))}}}])

(defn- routes []
  ["/" [["" (-> start-page (tag :index))]
        [:get [["login" (-> login-page (tag :login))]]]]])

(defn- routes []
  ["/" [["" (-> start-page (tag :index))]
        ["login" [[:get ["" (-> login-page (tag :login))]]]]]])
As far as I can see all of the above should actually work. I guess I'm only posting these to show I've tried 🙂 Finally I'd like to add that I'm using these routes in ClojureScript. Does someone have experience with bidi and can help me understand what I'm doing wrong?


Having hyphen in folder name gives error but when i rename test_utils to testutils it works

java.lang.Exception: namespace '' not found after loading '/com/pay/boomerang/config', compiling:(com/pay/test_utils/helpers.clj:1:1)
there has been a similar question posted here but no actual reason of the problem ->


Answered in #clojure (it's best not to post a question in multiple channels, by the way).


There’s some implicit mapping that happens between namespace names and filesystem paths, so in clojure maps to the file com/my/name_space.clj


It should be a dash in Clojure, and an underscore in the filesystem.


possible to use with matrix or how to create/manipulate matrix without repos?


(Hackerrank challenge)


is there any way to read a line from an input stream without skipping it in the buffer?


so you would call .mark, save the result, attempt to read a line, then call .reset passing the mark back in


if you are reading by lines you should be using a BufferedReader already


oh okay cool so I need to do a mark rdr and then call .reset and it’ll reset the position in the reader


@alexkeyes I was slightly incorrect - there’s only one mark supported per BufferedReader

user=> (require '[ :as io])
user=> (import ( StringReader))
user=> (def rdr (io/reader (StringReader. "hello\nworld")))
user=> (.mark rdr 127)
user=> (.readLine rdr)
user=> (.reset rdr)
user=> (.readLine rdr)


that’s fine I only need one


for an alternate API there’s PushbackReader, where instead of mark and reset, you read and then unread


but that doesn’t seem to have a simple readLine


@alexkeyes Your situation may have unique requirements, but in general I would recommend getting away from the java interfaces ASAP by dumping all the data into a clojure datastructure ASAP, then cleaning the data afterwards, removing empty lines, whitespace, errata etc


That way I keep most of my logic in clojure-land. Granted, some efficiency concerns will have you preferring the java interfaces sometimes.


immediately after the bit where I am mucking about the program moves the input stream into clojure land


Yeah, I figured


when i try to use refresh

(use '[ :only (refresh)])
'com.boomerang.hello' not found after loading '/com/boomerang/hello'
The hello.clj is basically
(ns com.boomerang.hello
    :extends  java.util.Arraylist))


I'm assuming seeing as you're using gen-class that you're aoting things? tools.namespace doesn't support aot'd stuff


@bfabry then how do i use gen-class in my project ?


you can still use it, it just won't play nicely with tools.namespace


so you'll need to be careful about source paths and build steps


personally I just wouldn't use it, I've always found it a massive pain


@kevinbheda I would only use :gen-class if you want to produce .class files for direct consumption by non-Clojure JVM languages. AOT in general is a giant pain and has all sorts of caveats. It's very rarely needed but unfortunately it seems to have become the default recommendation for apps written in Clojure 😞


We don't use :gen-class or AOT for anything at all at work.


@seancorfield the problem want to use java grpc . I cant do it without gen-class example here


I suspect you could work with Java gRPC without AOT but you couldn't use that library. I've gone down the :gen-class path with Clojure code several times (early on) and nearly always regretted it.


(I don't know enough about gRPC to offer guidance but if I were attempting that, I'd explore alternatives first and only resort to :gen-class if I couldn't find a "better" way)


We build uberjars without it, and then specify the entry point when starting the JAR: java -jar path/to/the.jar -m entry.point and that runs entry.point/-main.


(this leverages the clojure.main namespace as the declared :main when building the uberjar)


@seancorfield what do you use as a runner (I ask because the only reason I use AOT is so that jsvc knows how to run my app)


We have an init.d script (and it configures JVM options etc based on the service being started -- and accounts for a couple of our older processes being run directly via Boot instead of as uberjars).


we use AOT on uberjar but not in dev. compile time turned out to be significant performance wise


Looking at the jsvc docs, it seems you could tell it clojure.main was the class to run and then provide -m entry.point as command line arguments?


in places where we need a defined java class for a java process to pick up we write a java shim over aot+gen-class


Oh, I see it expects a Daemon class?


@seancorfield yeah, and I have a small shim that implements Daemon then uses require / resolve at runtime to run our real code, that way we avoid many of the aot problems (the namespace we aot has no logic beyond the require / resolve so I don’t need to mess with it during dev)


since aot is contagious it would otherwise spread to all our other namespaces, but since it only uses require inside a function at runtime, the contagion does not spread


maybe we could get all the things we need from init.d though - that would certainly be simpler if so


A simple beginner question... aot is bad?


For production


If yes... could you explain the reason please


aot is a tool that is useful in a small number of scenarios. it is a tool with quite sharp edges and poky bits


there are things that can go wrong in aot code that won’t affect code that isn’t aot compiled


so if it’s possible to avoid it, you gain a reduction of complexity, and fewer corner cases to worry about


TBH, my biggest beef with AOT is the contagion. A JIRA issue has been open for years about that I believe...


in return for that trouble, aot gives you… code that java code can run without using - which - that’s a benefit, but a small one


it also gives you code that loads much quicker when you :require it. which is useful for.... people whose code is executed by some sort of distributed service and that's about it


So, if I'm developing a library, aot would be a benefit


never use aot for libraries, that breaks things all over the place


Type ahead makes difference on aot?


because it forces all your consumers to use the exact versions you used of every dep you use


Sorry... typehint


type hints and aot are orthogonal


I'm still a little lost... it make any difference in performance? Production that is longrun


it is a small change to startup time, no change in runtime performance


clojure is always a compiler, it doesn’t have an interpreted mode


it makes a difference in the performance of code loading, which matters to very few people. for those it does matter to they can always AOT the code they consume


yeah - usually it’s good to avoid AOT, but if you need it, it’s better to do it at the app level, doing it in a lib just causes problems


If you are developing a desktop app, that maybe needs a fast startup, so use it, otherwise, server (Back) apps you don't need it, its better to avoid it then


yeah, I could see aot compiling a desktop app if you are delivering a jar


it wouldn't make enough of a difference to bother with a desktop app, because it only starts the process once, not enough cost. it makes sense in my particular case because the process gets started many hundreds of thousands of times


there’s also cases where you really do need some java thing to be able to call your code, and the thing calling it is not flexible enough to use to do it, and there’s use for AOT there too


I see... I'm understanding a little better... but I didn't understood about the typehint.. I don't know what orthogonal means (the translation is no good)


just a pointlessly fancy was of saying "unrelated"


they don’t have anything to do with one another


I see.. typehint helps in runtime performance, when interop with java, right?


Even when we don't use aot


right, it helps the clojure compiler emit better code


I see, thanks


whether you use aot or not, clojure still emits the same code (except gen-class which is aot only)


the type hints do the same thing in code where you don’t have aot


I see... thanks


Só aot is recommended just if you use the clojure api, otherwise avoid it


it’s for when you are using java to call clojure code, and the java code can’t use the class


Okey, thanks


TL;DR: AOT Bad! 😆