Fork me on GitHub
Michael W04:06:38

I have a function that I need help simplifying. I cannot figure out how to reduce the duplication here and it's driving me nuts. query+ here: It's a simple toy I am using to learn clojure.


You could write a function that accepts a string and does the three defs, and then run! that function over a list of all the things you want the shortcuts for.


(it might be easier to do it with a macro since def is a special form, but you could use intern instead I think)

Michael W04:06:48

I guess I don't understand where the string would come from

Michael W04:06:15

I'm thinking about the duplication of the let expressions in query+ I think I should be able to simplify that duplication down to just the function I create for the future.


@UAB2NMK25 what about this

(defn query+
  "asynchronous query to
    `action` required: people planets films starships vehicles species
    `id` optional"
  [pool action & args]
  (let [deferred (d/deferred pool)
         id (first args)
         chain (d/chain deferred #(future (if id (query! action %) (query! %))))]
    (d/success! deferred (or id action))

Michael W00:06:05

That is exactly what I was trying to think of, I forget that if is just another expression and not a special form like in other languages.


Cool. Yeah, that shift from statements and special forms in some languages to a very uniform expression-based approach in Clojure can be a big shift. I actually have problems when I have to go the other way and deal with some non-Clojure code.


We have a legacy code base that I still have to work in from time to time and I quite often write something that is too "Clojure-y" for that language's compiler 🙂

Michael W03:06:50

Thanks again for the help, I updated github with the changes and my first macro. I am really liking this language.


I'm very happy we made the change to Clojure ten years ago. I've never been happier with a language in my 35+ years of software development!

Michael W04:06:38

It works perfectly the way it is but that duplication just bugs my ocd.


Which duplication are you trying to get rid of then? Sorry, I thought you meant all those triple def expressions.


I wasn't trying to solve any duplication inside query+ sorry 🙂


For some reason my docker file with lein uberjar in it gives the following error on a push

[Enumerating objects: 1986, done.
Counting objects: 100% (1984/1984), done.
Delta compression using up to 16 threads
Compressing objects: 100% (1901/1901), done.
Writing objects: 100% (1942/1942), 28.23 MiB | 1.87 MiB/s, done.
Total 1942 (delta 646), reused 0 (delta 0)
remote: Compressing source files... done.        
remote: Building source:        
remote: === Fetching app code
remote: === Building web (Dockerfile)        
remote: =!= Dockerfile parse error line 40: unknown instruction: LEIN        
remote: Verifying deploy...
remote: !	Push rejected to vendomarch.        
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to ''


@pshar10 Dockerfile parse error line 40: unknown instruction: LEIN is probably a big clue...


@seancorfield lein works in the console directly


I thought that would be obvious


Your Dockerfile is invalid according to that error.


@seancorfield you know docker? Here you go:

# We will use Ubuntu for our image
FROM ubuntu:latest

# Updating Ubuntu packages


RUN apt-get -qq update && apt-get -qq -y install curl wget bzip2 openjdk-8-jdk-headless \
    && curl -sSL  -o /tmp/ \
    #    && curl -sSL  -o /tmp/ \
    && bash /tmp/ -bfp /usr/local \
    && rm -rf /tmp/ \
    && conda install -y python=3 \
    && conda update conda \
    && curl -o install-clojure  \
    && chmod +x install-clojure \
    && ./install-clojure && rm install-clojure \
    # no need to install lein
    && wget  \
    && chmod a+x lein \
    && mv lein /usr/bin \

    && apt-get -qq -y autoremove \
    && apt-get autoclean \
    && rm -rf /var/lib/apt/lists/* /var/log/dpkg.log \
    && conda clean --all --yes

ENV PATH /opt/conda/bin:$PATH

RUN conda create -n pyclj python=3.7 && conda install -n pyclj numpy mxnet \
    && conda install -c conda-forge opencv
## To install pip packages into the pyclj environment do
RUN conda run -n pyclj python3 -mpip install numpy opencv-python

FROM openjdk:8-alpine
lein uberjar
COPY target/uberjar/vendo.jar /vendo/app.jar


CMD ["java", "-jar", "/vendo/app.jar", "--server.port=$PORT"]


Don't post walls of text into Slack -- they're unreadable.


Can you post a link to this code on GitHub instead?


That way we can see line numbers and also clone it to look at.


it's not on it. Just read it @seancorfield.

picard-facepalm 12
👎 23

Don't be rude. I'm trying to help you.


Your Dockerfile has a syntax error. Read teh error yourself.


Look at line 40 -- it is NOT valid.


You call “lein uberjar” but every other she’ll command is behind a RUN syntax


Hey! I pointed out what the error was in your file.

👆 20

You are being very rude.


I feel compelled to tell you that when I first started learning clojure 1-2 years ago, I was really impressed by how often you helped new people, me included. And I'm astonished that after all that time, you still do it. Really big thanks!

❤️ 28

come on guys, keep it civil 🙂


brand new to Clojure! Any help would be much appreciated on best resources to get started at? Videos, articles, guides, etc. Thanks in advance! I am a PowerShell / .NET / VB scripter with some PHP and javascript experience and now wanting to learn Clojure as I have heard so much good stuff about it 🙂


This was the first Clojure/Rich Hickey talk I watched back in 2013


I highly recommend it


awesome thanks! I will take a look. Then where do you recommend I start with the basics of learning clojure and experimenting? Any good trainings/tutorials/youtube channels/videos/guides etc.?


Depends on your style of learning… I picked up a book and started typing in examples


After a few weeks/months of practice, tried to make a working backed API with it; that’s where you learn the most

👍 4

This is a very good guide IMO


It’s a bit dated


but very good


thanks I actually have that on my list from another recommendation so x2 means I should definitely start there at clojure from the ground up. Appreciate it.


“bit dated” I mean that you don’t really need to use “lein” nowadays, you can just “brew install clojure” (on Mac)


(not sure what you environment is)


But the apart from the build tools, the advice in Aphyr’s guides is very solid and probably will never be dated as far as Clojure the language is concerned


I am on Windows... I know people will probably laugh at me 😉


No they won’t; I was a long-time Windows user myself before I switched to Linux and MacOS later


I can’t be of much help with Windows specifically nowadays, but other than that, happy to help!


Ok so I wanted to organize the "from the ground up" course and I notieced that there were plans in the 2nd to last post titled Roadmap of a bunch more stuff and then it seemed to end with the "debugging" chapter? Do you know if that is the case? or did it finish / continue somewhere else?


I have the following: 1. Welcome 2. Basic types 3. functions 4. sequences 5. macros 6. state 7. logistics 8. modeling 9. *roadmap* 10. debugging And then it kind of suddenly ended?


I suspect the author thought it was a "good enough" guide to get folks started and just hoped he might come back to it and extend it some day...


Just seen your comment about Windows -- that will definitely make your Clojure learning journey harder: most of the tooling and books / tutorials are written for macOS/Linux. There is a lein.bat for Windows -- I can't remember how smooth that process is (I haven't really used Leiningen for years now).


Since you are comfortable with Powershell, you might consider going the Scoop installer route and using the Clojure CLI / deps.edn stuff that is described on but using the Scoop installer described at the bottom of


I use Scoop on Windows and the Clojure CLI / deps.edn stuff (on macOS/Linux, I use Homebrew -- but still the Clojure CLI / deps.edn stuff).


At least with Scoop, it also makes it easy to install a JDK (Java/JVM) and various other useful Clojure tools (like clj-kondo the command line linter behind the linter-kondo package for Atom).


@samdynamicsllc yea it’s not a complete end-to-end guide but it’s enough to get you started; it’s more like quality vs quantity type of thing


@samdynamicsllc I have over 70 hours of videos on Clojure at and a few books to help too.


Wow @U05254DQM that’s amazing! Thanks! Do you have a recommendation where to start? There Is alot there!


It depends what you want to learn. I have a collection of play lists that separate the videos into groups, see the list of playlists on To practice Clojure and learn some of the clojure.core library, then is a great site. I have guides that walk through the first 60 or so challenges, but try solve them yourself first, especially the first 20 challenges 🙂 If you want to build something, then there is the webapps playlist and I will dig out some of the ClojureScript single page apps videos and create a playlist for those too. I am also updating the practicalli Clojure book, which should give a more clearer structure to learning Clojure. I recommend using deps.edn projects and the Clojure command line tools, although there is nothing wrong with Leiningen, these newer tools I find a bit more flexible and simpler to work with. If you are on developing on Windows, then I recommend the #clj-on-windows channel for help with some Clojure tooling if you get stuck, although if you have powershell everything should work okay. I think is the recommended approach for installing Clojure


Amazing! Thanks so much. I just joined that channel and I’ll start digging into all your stuff. Much appreciated.


@samdynamicsllc very cool… I came to Clojure myself from a PHP background

👍 4

@pshar10 Please be nice to people helping you and everyone else here. Being rude here discourages people helping - don't do it.

🎯 32

Q: I have a small function that uses loop/recur. Inside it I have an if. On the if true path, I want to do more than one thing - I want to print and I want to recur. Is this possible? The function works fine if I just recur, but I can't figure out how to print. I thought I needed do to print and then recur, but can't figure it out.


You can fit multiple things into a single expression using (do ...) . E.g.

(if true
    (println "") something else...)
  (...this is the else part...))


The last thing in the do will be returned.


Function body, let, even loop/recur have an implicit do inside - this is why you can have multiple expressions in them.


If you can post what you have tried, I can check what is going wrong.


@UJRDALZA5 I got it. I must have made a syntax error and didn't see it - and that got me confused - as the do works fine


Oops sorry! (defn read-input [^Terminal terminal] (loop [keystroke (. terminal readInput) result ""] (if (= :enter (key-codes (. keystroke getKeyType))) (str result) (do (put-string terminal (str (. keystroke getCharacter))) (recur (. terminal readInput) (str result (. keystroke getCharacter)) ) ) ) ) )


@UJRDALZA5 thanks, got the rest of it working. Appreciated!

👍 8

Has anyone made custom filters with Selmer before? I would like to add a filter to do bold or underlined text, but just small segments within larger strings. Like "Hey there :u:world:u:" would underline world ... any advice on how i can go about getting this behavior?


Or maybe some other way of doing what are effectively custom HTML tags in selmer


Hello, I downloaded clojure CLI Tools throught powershell on Windows 10. But when I type "clj", I get that message: "Error: Could not find or load main class clojure.main". Anyone had that problem?


Is your Java setup properly?


i set path to JAVA_HOME like that C:\Program Files\Java\jdk1.8.0_251


But before it was jre. After seeking the way to resolve problem I installed Jdk, but it not resolve problem


Are you running clj command in a project root directory? EDIT: That should not matter. Just tried on my machine.


it is not working for you too? I tryed to call it inside the Modules/ClojureTools, but it not help at all.


@U014M4DMY7L When you say you "downloaded clojure CLI Tools" for Powershell, what steps exactly did you take? Scoop is really the easiest way to get it working on Windows (and that can install Java and other tools too).


I am just execute this file via powershell as administrator ->


I am tried scoop and all go well until this Creating shim for 'cmd-clojure'. Can't shim 'powershell.exe': File doesn't exist. <- I was followed that instruction, but when i got this on "scoop install clojure". Why it can't find powershell.exe?


Hmm, that is odd... can you jump into #clj-on-windows and provide some details and tag @UBLU3FQRZ there in your question? (he's more likely to see it in that channel and there are a bunch of Windows users there who might be able to help in more detail)

Clark Urzo15:06:33

Going through a bunch of Clojure books right now after being fed up with JS for the nth time

Clark Urzo16:06:47

Really, really minor thing, but I just wanted to ask: why does indexing in anonymous functions start from 1 instead of 0?

Clark Urzo16:06:40

Like, I expected #(* %0 %1) would work but apparently the first argument is indeed bound to %1

Clark Urzo16:06:59

Does %0 carry a special meaning in other contexts? E.g., the name of the file being called like in Bash, or...?

Michael J Dorian16:06:40

I don't think it's always wrong to index starting at one. I would say "the first argument" if I were speaking about it. There may or may not be a specific rational but it feels natural to me

👍 4

there are no reasons to start indexing with 0 ) in any context or language )

Michael J Dorian16:06:43

I wouldn't say that either. 🤷


> Does `%0` carry a special meaning in other contexts? the answer would be - no, there are no special meaning for %0 in clojure

👍 4
Clark Urzo16:06:46

But it really is just a minor thing and I don’t want to start a fight so...yeah thanks! Load off my mind.


it is just a convention syntax, that’s all


I think the fact that in a shell $0 is the function / script itself, and $1 is the first arg could be related to #() args starting with %1


but % has no meaning outside #() blocks


mod could have been named % but clearly wasn't

Clark Urzo16:06:55

@noisesmith Yeah, that was my first guess as well.

Clark Urzo16:06:09

But I guess maybe I’m just reading into it too much


conventions come from a lot of places and the only rule is that things seem familiar and unsurprising


and once it's implemented, you need to stick with it for simple compatibility reasons


there is one thing that surprise me a bit when I first saw it: you can use % and %1 in the same lambda and they both will stand for “first argument” (#(prn % %1 %2) 1 2)

Cas Shun16:06:41

Is there a function to to go from :ns/key to "ns/key", or do I need to do something like (subs (str :ns/key) 1)


user=> (symbol :foo/bar)
if you call str on the symbol you get what you expect


bonus, this also works with non-namespaced keywords

Cas Shun16:06:41

user=> (symbol :foo/bar)
ClassCastException clojure.lang.Keyword cannot be cast to java.lang.String


you need a newer version of clojure


check clojure-version

Cas Shun16:06:56

Ok cool, I see. Project I'm hacking on is on 1.8


Hi everyone, I'm working through Clojure for the Brave and True and have been confused why my implementation of update-in won't work. I figured (nudged by the proximity to the exercise "implement assoc-in") that I could implement it in terms of assoc-in, and attempted to do so with the code block below, but this throws up either ArityException or ClassCastException with everything I test it with. Is there some subtlety I'm missing here?

Kazuki Yokoyama17:06:15

I'm not sure the syntax [& ks] will work as you expect in the parameters list. Since ks is already a collection, you have to do nothing but [m ks f & args] (this is the signature of the update-in method). Another point is that args are collected as a sequence, so you have to "split" them when you call f . One way to accomplish it is with (apply (partial f (get-in m ks)) args) .


thank you, this is very helpful!

👍 4

(defn alt-update-in
  [m [& ks] f & args]
  ((assoc-in m [ks] (f (get-in m ks) args))))


@srdocherty ((f)) means "call f, then call whatever f returns"


it's pretty much never rarely what you want


another way to put it which helped me: (f) in clojure is the same as f() in js etc. so ((f)) is the same as f()()

👁️ 4

@srdocherty regarding the exception - this is why you get arity exception:

user=> ({})
Execution error (ArityException) at user/eval191 (REPL:1).
Wrong number of args (0) passed to: clojure.lang.PersistentArrayMap
and this is why you get a class cast exception
user=> (1)
Execution error (ClassCastException) at user/eval193 (REPL:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')


a map is a function, but needs a key when you call it, most other things just aren't functions


from another angle (maybe the most intuitive one): parens aren't free in clojure, adding them changes the meaning of the thing you wrapped by attempting some operation


also, more subtly, ks is already a collection, putting it in [ks] isn't what you want


Aha, so the first problem is that assoc-in shouldn't be wrapped in its own parentheses for the function body, as it's trying to call the map that assoc-in produces as a function without an argument


right - one layer of parens is enough


I'm not sure what you meant by "in its own parenthesis" as it already had its own, and extra were added after that


haha yes, that was a bad way of putting it. Thanks for the pointers!

🍻 4

In general in all Lisp family languages, including Clojure, parentheses are significant. In the right-hand side of an assignment statement in Java/C/C++, etc., you can often add "redundant parentheses" around parts of an expression, and it still means the same thing. That is not true in Lisps.


on the other hand adding an extra () to the right of an expression in those languages is the same error we saw here


(or same confusing behavior, when the thing was technically invocable but that wasn't the intention)


Does 4clojure not support lazy sequences? I put an answer to #137 that works in, using a lazy sequence, but results in a "java.lang.ArithmeticException: integer overflow" in 4clojure


Did you attempt all of the tests that 4clojure shows for that, when using A couple of those tests have potential for overflow, depending on your solution...


(I don't think 4clojure runs additional tests that it doesn't show)


to address the direct question, 4clojure fully supports laziness


I'm trying to think of how you'd get integer overflow in one place and not the other - it could be related to 4clojure using 1.5, where some ops might not auto-promote the same way they do now(?)


All test cases work, but the first case produces the overflow on 4clojure


do you mind sharing the code?


We'll do it in a thread


(fn [numm base]
  (let [expt   (fn [x n] (reduce * (repeat n x)))
        powers (take-while #(or (<= % numm) (= % 1)) (map #(expt base %) (range)))]
    (second (reduce
      (fn [[value arr] cur] [(mod value cur) (conj arr (quot value cur))])
      [numm []]
      (reverse powers)))))


OK - I can replicate that error in 4clojure, and not in my local repl - I am going to try older clojure and see what the actual error is...


so this is the stack trace:


java.lang.ArithmeticException: integer overflow
        at clojure.lang.Numbers.throwIntOverflow(
        at clojure.lang.Numbers.multiply(
        at clojure.lang.Numbers$LongOps.multiply(
        at clojure.lang.Numbers.multiply(
        at clojure.core$_STAR_.invoke(core.clj:951)
        at clojure.core.protocols$fn__5558.invoke(protocols.clj:64)
        at clojure.core.protocols$fn__5543$G__5538__5552.invoke(protocols.clj:11)
        at clojure.core$reduce.invoke(core.clj:5995)
        at clojure.core$reduce.invoke(core.clj:5991)
        at user$f$expt__20.invoke(foo.clj:3)
        at user$f$fn__25.invoke(foo.clj:6)
        at clojure.core$map$fn__3811.invoke(core.clj:2430)
        at clojure.lang.LazySeq.sval(
        at clojure.lang.LazySeq.seq(
        at clojure.lang.RT.seq(
        at clojure.core$seq.invoke(core.clj:133)
        at clojure.core$take_while$fn__3840.invoke(core.clj:2509)
        at clojure.lang.LazySeq.sval(
        at clojure.lang.LazySeq.seq(
        at clojure.lang.RT.seq(
        at clojure.core$seq.invoke(core.clj:133)
        at clojure.core$print_sequential.invoke(core_print.clj:46)
        at clojure.core$fn__4990.invoke(core_print.clj:140)
        at clojure.lang.MultiFn.invoke(
        at clojure.core$pr_on.invoke(core.clj:3264)
        at clojure.core$pr.invoke(core.clj:3276)
        at clojure.lang.AFn.applyToHelper(
        at clojure.lang.RestFn.applyTo(
        at clojure.core$apply.invoke(core.clj:600)
        at clojure.core$pr.doInvoke(core.clj:3282)
        at clojure.lang.RestFn.applyTo(
        at clojure.core$apply.invoke(core.clj:600)
        at clojure.core$prn.doInvoke(core.clj:3309)
        at clojure.lang.RestFn.applyTo(
        at clojure.core$apply.invoke(core.clj:600)
        at clojure.core$println.doInvoke(core.clj:3329)
        at clojure.lang.RestFn.invoke(
        at user$f.invoke(foo.clj:7)
        at user$eval32.invoke(283b967690b743aa3c81baf2afdf34941270d357d78e11bc4f8e9c68e1
        at clojure.lang.Compiler.eval(
        at clojure.lang.Compiler.eval(
        at clojure.core$eval.invoke(core.clj:2795)
        at clojure.main$repl$read_eval_print__5967.invoke(main.clj:244)
        at clojure.main$repl$fn__5972.invoke(main.clj:265)
        at clojure.main$repl.doInvoke(main.clj:265)
        at clojure.lang.RestFn.invoke(
        at clojure.main$repl_opt.invoke(main.clj:331)
        at clojure.main$main.doInvoke(main.clj:427)
        at clojure.lang.RestFn.invoke(
        at clojure.lang.Var.invoke(
        at clojure.lang.AFn.applyToHelper(
        at clojure.lang.Var.applyTo(
        at clojure.main.main(
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAc
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Delegating
        at java.base/java.lang.reflect.Method.invoke(
        at clojure.lang.Reflector.invokeMatchingMethod(
        at clojure.lang.Reflector.invokeStaticMethod(
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAc
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Delegating
        at java.base/java.lang.reflect.Method.invoke(
        at clojure.lang.Reflector.invokeMatchingMethod(
        at clojure.lang.Reflector.invokeStaticMethod(
        at user$eval3.invoke(283b967690b743aa3c81baf2afdf34941270d357d78e11bc4f8e9c68e1b
        at clojure.lang.Compiler.eval(
        at clojure.lang.Compiler.eval(
        at clojure.lang.Compiler.load(
        at clojure.lang.Compiler.loadFile(
        at clojure.main$load_script.invoke(main.clj:282)
        at clojure.main$init_opt.invoke(main.clj:287)
        at clojure.main$initialize.invoke(main.clj:315)
        at clojure.main$null_opt.invoke(main.clj:348)
        at clojure.main$main.doInvoke(main.clj:426)
        at clojure.lang.RestFn.invoke(
        at clojure.lang.Var.invoke(
        at clojure.lang.AFn.applyToHelper(
        at clojure.lang.Var.applyTo(
        at clojure.main.main(


replacing * with *' fixed it


unlike , ' auto-promotes - I'm not sure why expt was big enough to overflow though


Huh. Interesting. Was it the clojure version that made the difference as you predicted?


oh I bet this is about the chunking behavior of range


right, I replicated by using an older clojure, as I recall range used to be more aggressive about chunking, and chunking makes things less lazy


Interesting. I'm truly a beginner but I'm glad my assessment of it being related to laziness wasn't far off. Thanks a lot


by adding (println "expt" x n) to expt I figured out that it was chunking


expt 10 0
expt 10 1
expt 10 2
expt 10 3
expt 10 4
expt 10 5
expt 10 6
expt 10 7
expt 10 8
expt 10 9
expt 10 10
expt 10 11
expt 10 12
expt 10 13
expt 10 14
expt 10 15
expt 10 16
expt 10 17
expt 10 18
expt 10 19
expt 10 20
expt 10 21
expt 10 22
expt 10 23
expt 10 24
expt 10 25
expt 10 26
expt 10 27
expt 10 28
expt 10 29
expt 10 30
expt 10 31


Good to know


so yeah, it was "chunking" - 32 was the magic number for chunked seqs


1.10 stops at expt 10 7


you can fix your code directly by using *' - but you can also improve it (and make it do less CPU work calculating exponents) by using iterate or reductions instead of map (since each number in the sequence can use the previous total in iterate or reduce, but in map they need to recalculate from the beginning)


that's true. I always try to maximize some metric during each problem (readability, simplicity, etc). In this case, time efficiency was what I was going for because of the intensity of exponents


another approach is to always modulo by the base and quotent until 0


then you dont' even need the exponentiation


the repeated divides are also expensive of course


Anybody able to point me towards why my lein repl will not function? I am able to start the repl with cider. I am on windows. It just hangs here.


You are running a shell inside of an Emacs buffer, and in that shell buffer starting lein repl ? And all of this on Windows?


I would wonder whether lein repl works well on any OS when started from within an Emacs shell buffer.


If I use powershell everything seems to work fine. How do I have the repl in an emacs buffer instead?


monroe is meant to be used this way iirc


Thank you


Works fine for at least eval'ing (+ 1 5) on Linux and macOS, so I take back my last comment. I just normally never run lein repl that way.