Fork me on GitHub

Is there a de-facto library to interact with AWS APIs? I need to talk to EC2, IAM, STS, Lambda, RDS, DynamoDB, CloudWatch and several others. Any suggestions will be greatly appreciated.


I recommend either: • The official Java API •


the latter is very nice from clojure, but it’s been around a lot shorter than the official API (like a year or so)


thank you, @U07S8JGF7! i’ll take a look.


that cognitect-labs library looks great! now i need to figure out how to use a custom profile with this and it’ll be fun 🙂 thanks again!


I do not recommend amazonica.


It wraps the official java lib, exposes renamed methods via reflection, and does so in a way that doesn't allow access to the underlying client object.


In addition, all interactions with it are variadic named args, meaning that it doesn't even expose a good data-oriented API.


IOW - it takes away some value (exposing the client is useful!) and the only value it adds is renaming args and using keywords. IMO it's basically a vanity lib ("I want to type what I want to type.")

Ben Sless08:05:48

Good reasons. Thanks for the explanation


i had seen Amazonica but as a noob it was difficult to get started with compared to Cognitect’s aws-api (which has been a lot of fun to play with.)

David Pham11:05:38

In Clojure Spec, is it possible to instrument a function and set its specs on the fly? More precisely, suppose a fspec is defined as following (s/def ::f (s/fspec :args integer? :ret zero?)). How can apply ::f to several functions and use generator to check if the arguments follows this specs?

Alex Miller (Clojure team)12:05:41

You have to use s/fdef for check to work

Alex Miller (Clojure team)12:05:24

But you can use s/fdef to set multiple functions with that ::f

👍 4

Are there any limitations with keywords? If I have a REST API that accepts JSON and I have a library that parses the keys into keywords, is this safe for general user input? Or am I mixing things up with Erlang where there's a limit to the number of atoms so you don't provide untrusted access to atom creation?


Likewise a beginner myself - but I think having a function that transforms {"firstname" "Joe"} to {:firstname "Joe"} - is not the worst thing provided you check that - "Joe" is indeed a string - I think validating any user input is a good place to use spec


On that note, I use this little fn to “clojurise” JSON keys: It can be used directly with Cheshire (JSON parsing lib) like this: One thing to note is that it doesn’t handle conflicts e.g. a JSON object with keys “firstName” and “first_name” (which is arguably poor JSON schema design, albeit technically possible).


keywords are kept in a weak hash for interning (so that two keywords that are equal are the same object), before it was a weak hash there was a memory problem with making large numbers of keywords


the limits are probably higher but the principles are the same


I try not to keywordize until after basic validation, but that is not a common position


there are no hard limits on keywords besides the total memory in a JVM. Keywords are interned into a table


Would the JVM garbage collect them eventually?


That's the problem with Erlang, they're never dropped so they needed to be bounded (okay, a few million, but it was a potential dos)


eventually yes


Okay so should be fine. It's the default for the middleware in and the API is internal


Thank you!


just for my own curiosity - (keyword "foo") - will create new keyword only once (in the same namespace) - no matter how many times I call it - i.e. the memory is allocated the first time - and rest of the time it's a lookup?


it does not even matter in which namespace you calling it

👍 8
Frances He14:05:32

Hi Guys, I just started to learn Clojure and found this community

Frances He14:05:30

And I am following the tutorial [Learning Clojure from ground up](

Frances He14:05:19

And get stuck after trying to launch repl...

Frances He14:05:24

➜  scratch lein repl

Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 52012 on host - 
[2]  + 71305 suspended  lein repl

Frances He14:05:48

And google search try to find any solution, no luck...

Frances He14:05:56

Wonder anyone runs into the same problem?


what problem did you run into? not entirely sure what's going on


@hesiyun1996 Not sure if you meant to, but looks like you hit Ctrl-Z which is a bash shortcut to suspend the process. I bet if you run lein repl again and wait a few seconds you'll see the user=> prompt

Frances He14:05:38

nREPL server started on port 52012 on host - 


/tmp/whatever 
 ✔  lein repl
nREPL server started on port 54745 on host - 
REPL-y 0.4.4, nREPL 0.6.0
Clojure 1.10.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_202-b08
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e



do you not get something like this eventually?


(I also have the nprel server stuff)

Frances He14:05:06

hi, I got something like:

Frances He14:05:15

➜  scratch lein repl

Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 54972 on host - 
Tried to use insecure HTTP repository without TLS:

This is almost certainly a mistake; for details see

Frances He14:05:45

Reading the ING.

Frances He14:05:40

And just updated project.clj file as instructed in

Frances He14:05:55

It's just like taking forever for the script to continue...always stuck on on the line of launching server.


can you try this in a temp folder without a project.clj file?


mkdir /tmp/foo && cd /tmp/foo && lein repl

Frances He14:05:01

Now my zsh complains..Maybe something wrong with my lein setup, I'll double check it

Frances He14:05:13

zsh: command not found: lein

Frances He14:05:25

@dpsutton Thanks for your patience lol


weird. how did your path break


lol. no worries

Frances He14:05:46

Last time I did not follow lein's official page for install instruction, just borrow the quick set up from tutorial [Learning Clojure from ground up](

Frances He15:05:22

Now I'll just try to follow the homebrew way


yeah just install lein so that its on your path. brew or the official instructions

Frances He15:05:29

Is it normal to take such long time to use user=> prompt?

Frances He15:05:49

➜  foo lein repl
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 56115 on host - 

Frances He15:05:08

somehow still stuck on the sever prompt after brew it


it should be quite speedy


what is lein --version


and java -version

Frances He15:05:40

[1]  + 75363 suspended  lein repl
➜  foo java --version
java 14.0.1 2020-04-14
Java(TM) SE Runtime Environment (build 14.0.1+7)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)
➜  foo lein --version
Java HotSpot(TM) 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Leiningen 2.9.3 on Java 14.0.1 Java HotSpot(TM) 64-Bit Server VM
➜  foo


java 14 might not be the best


you could try java 13


or alternatively try brew install clojure/tools/clojure


which will install the clj and clojure cli tools

Frances He15:05:35

Looks like i already got clojure installed before lein

Frances He15:05:37

➜  foo which clojure
➜  foo brew install clojure/tools/clojure
Updating Homebrew...
Warning: clojure/tools/clojure is already installed and up-to-date
To reinstall, run `brew reinstall clojure

Frances He15:05:02

So my only option left is either downgrade java14 to 13 or have multiple version of java?


i don't know


i'm not sure if lein is compatible with java 14

Frances He15:05:03

What's your setup for running lein environment?

Frances He15:05:36

The official doc of lein said : OpenJDK version 8 is recommended at this time.

Frances He15:05:45

I'll try that


i think i use java 8 or 11 or 13 depending on computer

Frances He15:05:21

@dpsutton Thank you so much sutton! You've being really helpful 🙂


I run everything on OpenJDK 14 locally, including lein


(I was on lein 2.9.1, updating to 2.9.3 to double-check)


oh interesting. thanks for confirming sean. no idea what's going on here then


Updated to 2.9.3 and everything still works on OpenJDK 14

(! 547)-> java --version
openjdk 14 2020-03-17
OpenJDK Runtime Environment (build 14+36-1461)
OpenJDK 64-Bit Server VM (build 14+36-1461, mixed mode, sharing)

Thu May 14 08:37:06
(! 548)-> mkdir /tmp/foo && cd /tmp/foo && lein repl
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
nREPL server started on port 62294 on host - 
REPL-y 0.4.3, nREPL 0.6.0
Clojure 1.10.0
OpenJDK 64-Bit Server VM 14+36-1461
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

user=> Bye for now!

Thu May 14 08:37:30
(! 549)-> lein version
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Leiningen 2.9.1 on Java 14 OpenJDK 64-Bit Server VM

Thu May 14 08:37:34
(! 550)-> lein upgrade
The script at /Users/sean/bin/lein will be upgraded to the latest stable version.
Do you want to continue [Y/n]? 

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   137  100   137    0     0    321      0 --:--:-- --:--:-- --:--:--   321
100 13413  100 13413    0     0   7649      0  0:00:01  0:00:01 --:--:-- 57566
Downloading Leiningen to /Users/sean/.lein/self-installs/leiningen-2.9.3-standalone.jar now...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   637  100   637    0     0   1529      0 --:--:-- --:--:-- --:--:--  1527
100 13.9M  100 13.9M    0     0  2448k      0  0:00:05  0:00:05 --:--:-- 3074k
/Users/sean/.lein/self-installs/leiningen-2.9.3-standalone.jar.pending: OK
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Leiningen 2.9.3 on Java 14 OpenJDK 64-Bit Server VM

Thu May 14 08:37:50
(! 551)-> lein repl
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
:repositories detected in user-level profiles! [:clojars] 
nREPL server started on port 62326 on host - 
REPL-y 0.4.4, nREPL 0.6.0
Clojure 1.10.0
OpenJDK 64-Bit Server VM 14+36-1461
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e



Maybe IP6 vs IP4? Or maybe something bad in ~/.lein/profiles.clj ?


@hesiyun1996 What's in your ~/.lein folder?


Particularly, what's in your ~/.lein/profiles.clj file? That's often what breaks Leiningen (and why I wish more tutorials would recommend the official Clojure CLI tools instead of a) Leiningen and b) adding weird stuff to the profiles.clj file 😞 )

👍 4
❤️ 4
Frances He10:05:12

@U04V70XH6 Thanks for the follow up

Frances He10:05:54

@U04V70XH6 Looks like I don't have ~/.lein/profiles.clj file

Frances He10:05:23

➜  foo cat ~/.lein/
repl-port       self-installs/

Frances He09:05:03

@U04V70XH6 @dpsutton I finally resolved the issue...I am using emacs as my editor. And magically after i set up [cider:The Clojure Interactive Development Environment that Rocks for Emacs](, the lein repl command works as it should be

Frances He09:05:57

@U04V70XH6 @dpsutton My best guess is that somehow the emacs-clojure library solves the issue of clojure in emacs env setup? But, thanks you guys helping along the way 🙂

Frances He09:05:41

finally worked lol


That sounds unlikely. CIDER just invokes lein as seen by the “startup command” in your repl. I see there’s an “x” at the beginning of your project.clj form. Is that an errant typo?


Hi, I would like to format a number like 49780 in #Selmer template to show 49,780 using number-format but I don’t know how to do it. {{ratings-count|number-format:????}} . How can I format my number to show thousand separator?


user=> (require '[selmer.parser :as html])
user=> (html/render "{{n|number-format:\"%,d\"}}" {:n 49780})

aw_yeah 4

Maybe someone can add an example of that to

Charles H16:05:56

If I'm already a JavaScript pro and I learn me some Clojure, will picking up ClojureScript be easy peasy? Basically, I'm wondering if I should go and read a book on ClojureScript or not..

Charles H16:05:34

I do love some good technical reading so I might either way 😆


You should! Easy peasy depends on the person, but I’m sure you’ll enjoy it @charleshu

Charles H16:05:20

:thumbsup: any suggestions @christian.gonzalez?


What is the idiomatic way to get a file attribute, e.g, "creationTime" in clojure?

Alex Miller (Clojure team)17:05:37

The java.nio facilities are the best option


Hi Alex, thanks for your answer. I was just wondering if there was an idiomatic way to get the attributes.

(.toInstant (Files/getAttribute (.toPath f)
                                (into-array LinkOption [LinkOption/NOFOLLOW_LINKS]))
It would be nice if the Clojure API provided a way to get the file attributes in a native data structure, e.g. maps. But thanks anyway!

Alex Miller (Clojure team)17:05:59

Yep, Clojure’s io ns predates a lot of Java 7 apis and could use some updates for sure

👍 4

Especially now that v1.10 is JDK 8+ only. I assume it’s just a matter of time & priorities for this to happen? If Cognitect were to sketch out the desired interface (albeit the hard part), would they accept implementations from the community?

Alex Miller (Clojure team)17:05:08

given that that's not the hard part, not sure that's a likely sequence of events

Alex Miller (Clojure team)17:05:45

I've been doing a ton of file interop lately so starting to form some opinions but not likely to be an area we work on "soon"

Alex Miller (Clojure team)17:05:45

I think we'd probably want to take a light touch to anything in core (you can always augment with libs) so figuring out what's even in scope is problem 0


Right. And it would be ideal if the interface was at least somewhat portable to other runtimes (CLJS, Joker, etc.).


And FWIW by “hard part” I meant that public interfaces are hard because of politics / stylistic / future-proofness / portability considerations, not because they’re technically hard to write down…

Alex Miller (Clojure team)18:05:26

fyi, the namespaces are not designed to be portable (that's why they say "java")

Alex Miller (Clojure team)18:05:13

Java's historical legacy wrt File and Path is a huge pain and is probably the biggest complicating factor


Oh I know - I’ve been doing Java since 1997. 😉


Well I did - I no longer consider myself a Java guy since switching to Clojure. 😉

Alex Miller (Clojure team)18:05:36

there are so many nice things buried in the Paths and Files stuff now, it's irritating how often you have to change between those contexts


@U0MDMDYR3 and don't forget that the first step in contributing is to sign the CA and get yourself on this list 🙂


A task comes first, then a patch for that task that I think’s worth submitting, then the CLA. 😉


(I know that's not really the first step and not all types of contributions actually require a signed CA but 🙂 )


And there’s no way I’d go near this with a 40' barge pole without an interface definition that’s blessed by Cognitect. Too much risk of it being a complete waste of time…

Alex Miller (Clojure team)18:05:56

there actually is a jira for adding Path support already

Alex Miller (Clojure team)18:05:27

specifically for jio/file but that part at least is in the tracker


(that’s not a slam on Cognitect btw - I wouldn’t be happy for randos to define supported public interfaces for my code either)


@alexmiller I’ll check it out, and if there’s an interface definition (however draft it might be) might have a crack at an impl too.


I’ve been doing some scripting type work, and not having portability between Joker and, say, Planck has been a bit of an annoyance.


Plus my Clojure knowledge is 99.97% based on CLJ, so figuring out translations from CLJ API to Joker or Planck or whatever is also a friction point.

Alex Miller (Clojure team)18:05:46

I haven't looked at the ticket, I just know it exists

👍 4

I’ll see if I can find it.


And it already has a patch. 😉

Alex Miller (Clojure team)18:05:29

yeah, really just the tip of the iceberg

👍 4

I have a simple Clojure script:

[pomelo ~] cat test 
#! /usr/bin/clojure
(println "hello world")
[pomelo ~] time ./test 
hello world

real	0m0.739s
user	0m1.511s
sys	0m0.045s
Is there any way to dramatically improve the (startup) time?


@U0121PUL58W there sure is, I've been using babashka for these sorts of things


there's a #babashka channel for people who use it


it's a quick clojure interpreter that's built for scripting


Use ClojureScript (requires node runtime), babashka, or compile to native using GraalVM. Basically don't use the JVM, otherwise you will be dependent on JVM startup time as well as Clojure classloading time.


babashka looks very cool


you're welcome

Mr Bubbles19:05:18

Hello! I was wondering what the landscape was like for SSR + hydration in CLJS (esp Reagent). Most of the examples I've seen on GH just render static markup. What I would really like to do is use Machiatto or even plain node to optionally fetch some data, instantiate a store, inline it as EDN and have my main entry point parse the EDN, sync it to client, and do ReactDOM.hydrate on the root Reagent component

Mr Bubbles19:05:55

This is a pretty common use case in JS world, so the fact that there weren't any cljs examples got me wondering if I was missing something here

Dennis Tel19:05:04

Hi! I’m just getting started and I was wondering: How do you document what kind of arguments your function expects (for more complex functions other than adding numbers etc)? Is this what spec is for?


Mostly, folks describe that in a docstring. Spec can be used for that but the recommendation is not to spec "everything" -- just boundaries and "important" functions. Clojure is not a statically typed language and you shouldn't try to pretend it is.


Another option is :pre (& :post) to provide predicates on arguments (and return values) that will cause AssertionError if the arguments (or result) is not as expected. But those aren't in common use.


Does that help @dennistel90, or does it add more questions? (and "welcome to Clojure!")

Dennis Tel20:05:40

Oh no that helps! Was just wondering if Clojure had something like Elixir’s, which are purely for documenting functions and its arguments. Just wondering how you know with what to call a Clojure function. Or is this less of a requirement when working in Clojure?

Lennart Buit20:05:08

yeah you can use a (clojure.spec) s/fdef for that. That said, usually its pretty obvious what a function works on, for example by convension (`m` as a name of a map k as a name of a key …), or because in Clojure, most functions just work on all sorts of things, so map , for example, just works on sets, lists, vectors, etc.

👍 4
Lennart Buit20:05:41

There is this famous saying in clojure, that its better to create 1 function operating on n things than n functions operating on 1 thing.

Alex Miller (Clojure team)21:05:11

"It is better to have 100 functions operate on one data structure than to have 10 functions operate on 10 data structures." - Alan Perlis

💯 12
Mr Bubbles21:05:19

Another question 🙂 is it possible to stream EDN patches corresponding to the changes to one of the immutable collections? Or even observe what they are without manually creating a separate atom for each thing you want to keep track of?


I'm not sure if this is what you are asking, but with Clojure's built-in collections like maps, sets, vectors, etc., there are no changes to them, so no changes to track.

👍 4

There is only creating new collections from existing collections.


If you create a place like an atom, then it makes sense to say "what is the difference between the value contained within the atom at time X, versus the value it contained at time X+1?"


There are other 'places' one can create besides atoms, of course. There are multiple implementations around of CRDTs (Conflict-free Replicated Data Types) where the goal is to maintain a sequence of updating values for such collections over time, in a distributed system. Not sure if that might be in the neighborhood of what you are asking about.

Mr Bubbles21:05:39

Oh, good to know, thanks! Yeah, I worded that like a dope. Good to know there's a name for it, I think will give this a go


hello folks, just deleted .m2 folder by mistake and now clojure can't find class clojure.main


If you are using the Clojure CLI tools, e.g. clj and/or clojurecommands with a deps.edn file, it has its own separate cache of precomputed classpaths that often cache file name paths to files inside your .m2 directory. Using the -Sforce option should force it to recompute those paths.


Installing the Clojure CLI tools does not install anything in your .m2 directory.


In case it clarifies my earlier statement: Running clj or clojure commands can cause files to be added to your .m2, but installing the Clojure CLI tools by itself does not.

Alex Miller (Clojure team)22:05:22

clj -Sforce will force a re-download of libs


how can I remend that


If you’re on macOS, brew reinstall clojure is worth a shot.


I'm on windows


the command iwr ... didn't fix


(I don’t think that’ll resurrect .m2, btw, but at least it’ll get clj and clojure back for you)


I don't want to ressurrect my deps, it's okay, just fixing clj command


Not sure how best to reinstall Clojure CLI on Windows - sorry!


Been a looooooong time since I used Win. 😉


Hey there! Just starting and off to a bit of a rough start. If I create a new project with lein new figwheel sampleProject -- --reagent and then cd into the new directory and run lein figwheel I get:

Failed to compile build :dev from ["src"] in 0.798 seconds.
----  Could not Analyze  resources/public/js/compiled/out/reagent/impl/component.cljs  ----

  No such namespace: react, could not locate react.cljs, react.cljc, or JavaScript source providing "react"

----  Analysis Error : Please see resources/public/js/compiled/out/reagent/impl/component.cljs  ----
Figwheel: initial compile failed - outputting temporary helper application to resources/public/js/compiled/out/index.js
I’ve run lein clean as well as deleting my ~/.m2 folder, also re-installed clojure. Any tips to help fix this?


is there any package.json in your folder?


then run npm i


or npm install


and try again


That was it, thank you

🙂 4

interesting. i thought that figwheel started supporting the bundle target literally today lol. this template already is using bundle and a clojurescript 764 which is a newer version than 1.10.758 which says is current lol


you picked a heck of a day to start a new project 🙂


I didn't know about that lol, just used my sherlock holmes approach


and i forgot that @bhauman made that template which is why its hot off the presses. and there's already a new step to start up in the documentation for you @vinnyataide


it also prints out instructions when you run lein new figwheel example 😉


but I didn’t update the readme for lein-figwheel yet


my eyes flew right over it 🙂 i'm a terrible user


@dpsutton it's our friend @me1079 that needs it


someday I'll need it too but for now I'm using shadow-cljs


oops. sorry

Alex Miller (Clojure team)22:05:01

in about 45 minutes I'm doing an online talk at the Gateway Java User Group about Clojure for new Clojurists, particularly those coming from Java, in case anyone is interested. If you already know Clojure, probably not too useful. RSVP for info.

👏 12

ok just got it working on windows again


I've download leiningen and ran a self-install script


that reinstalled my clojure in .m2 folder


now clj is fixed


confusing to me that deleting the .m2 directory would do anything destructive. its just a cache

☝️ 4

it's a windows only gotcha

Alex Miller (Clojure team)22:05:04

it's not, but you need clj -Sforce to tell clj it's classpath is stale

Alex Miller (Clojure team)23:05:03

clj does not currently re-verify that the jars on the cached classpath actually exist. that's possible, but messy.


@alexmiller so to clarify, the install scripts do indeed put some “core” JARs needed for the correct functioning of clj/ clojure in ~/.m2?


(if so that’s a good thing to know, as I tend to whack ~/.m2 fairly regularly)


Ah ok cool. I wouldn’t have expected it to do that.

Alex Miller (Clojure team)23:05:29

But to run clojure.main, you need Clojure, which is on the classpath


I can double check, but I thought that merely installing clj / clojure commands can complete with no .m2 being created.

Alex Miller (Clojure team)23:05:20

The install is an uberjar


Cool. Means I can continue whacking ~/.m2 with impunity (aside from ISP charges…).


As mentioned earlier, you may find that unless you use -Sforce on later clj /`clojure` commands, you may get errors about missing classes. This can happen if the later clj / clojurecommand uses a cached classpath stored in a file inside the .cpcache directory that gives a full path to a file that was recently removed from .m2


Right. Or I just whack .cpcache too


that also does it


Although for a single user account there is one .m2directory, but there can be any number of .cpcachefiles strewn all over the place.


Right, though I happen to have a well defined root directory for all of my development, and I could just run something like find $DEV_ROOT_DIR -type d -name .cpcache -exec rm -r '{}' \; to clear things.


But very good to know that .cpcache has references into .m2.