Fork me on GitHub

I'm seeing if I can turn my project.clj into a deps.edn. Can't figure out using a github repo. E.g., :deps {com.github.cognitect/transcriptor {:git/url "" :sha "05e9eb093b21d9a3458e0d946ad9dab76ae1e1c8"}...} gives "Manifest type detected"


I do succeed, however, if I use com.cognitect/transcriptor {:mvn/version "0.1.5"}


(that last being, a verification that the library is includeable)


you need the url to the git repo


not the github webpage for the repo


yes of course


reasonable idea! but, no


status code is a 301


also the guide suggests a form like {:git/url "" :sha "04d2744549214b5cba04002b6875bdf59f9d88b6"}}} which..... seems like what I used


aren't the two forms [email protected]:foo/bar.git and the https form?


so I'd try [email protected]:cognitect-labs/transcriptor.git


no, if yo go to repo and click the clone button the url it gives you is the https url with .git


the root of the project does not contain a deps.edn


I tried successfully with the following deps.edn:

{:deps {clt {:git/url "" :sha "05e9eb093b21d9a3458e0d946ad9dab76ae1e1c8" :deps/root "examples"}}}


The examples subproject relies on the non-git version of transcriptor, however...


indeed, no benefit it seems to use a sha…


You can rely on a version of the examples project, but that doesn't get you transcriptor itself via git 🙂


ah, can :git/url not load projects based on a project.clj?


it appears not, ok


tools.deps does not understand project.clj -- only pom.xml and deps.edn (I think that's all)


yeah, that is the problem, it isn't a deps.edn project


Hi guys! Question: I have a spec defined like this:

(s/def ::person (s/keys :req [::foo ::bar ::baz]))
In another namespace, I need a similar spec like ::person, but with all keys as optional. Is there a way to copy the ::person spec and change the req keys into opt keys?


@vincentdm Not any easy way, no. This is a problem that Rich talked about at Conj and a future version of clojure.spec will address this.


Rings a bell! Okay, then I won't waste time in this avenue. Thanks!


The problem is that s/keys complects shape and requiredness.

Chris Kellendonk00:01:51

Hi all, new here. Not sure what the correct etiquette for asking new questions is but...Is there a built in function similar to clojure.core/time but allows for prepending a string to the output of elapsed time output. I find when using lots of time calls it can get confusing where they are from. I know it's simple enough to write this myself using do but just curious if there is already something built in?


@chriskellendonk probably easiest is to use with-out-str and then modify the string you capture

Chris Kellendonk00:01:48

Oh nice, thanks I didn't know that existed. I'll check it out looks pretty close to what I need


user=> (str "foo: " (subs (with-out-str (time (+ 1 1))) 1))
"foo: Elapsed time: 0.010721 msecs\"\n"


it's sloppy still, but it's a start

Chris Kellendonk00:01:55

Yeah I will probably just write my own helper to wrap this


And how do you get the original value in that case?

Chris Kellendonk00:01:41

ah good point, this does not pass the output through


Where did 2 go? 🙂

user=> (time (+ 1 1))
"Elapsed time: 0.038226 msecs"
user=> (with-out-str (time (+ 1 1)))
"\"Elapsed time: 0.009613 msecs\"\n"


yeah, you could use a promise or whatever to capture the return value


but that seems ugly

Chris Kellendonk00:01:20

I was using

(time (do (print "Timed =>") (+ 1 1)))

Chris Kellendonk00:01:40

which works, but was hoping this may be built in. Sounds like it's not though. Thanks for the help :+1:


Here's what we use:

(defmacro with-time
  "Evaluates expr and returns a map of the :value and the :time (in ms)."
  [key & expr]
  (let [value (if expr key :value)
        expr (if expr (first expr) key)]
    `(let [start# (System/nanoTime)
           ret# ~expr]
       {:time (/ (double (- (System/nanoTime) start#)) 1000000.0)
        ~value ret#})))


(ins)user=> (defn timed [f] (let [res (promise) timing (with-out-str (deliver res (time (f))))] {:result @res :time timing}))
(cmd)user=> (timed #(+ 1 1))
{:result 2, :time "\"Elapsed time: 0.029535 msecs\"\n"}


Return a hash map with the time and the value.


yeah, that macros probably the smarter bet


The docstring was not written with the public in mind 🙂

Chris Kellendonk00:01:19

I still want the value to be passed through as normal with time. I just want to add my own custom string so it reads "My string => Elapsed time: 0.029535 msec"


that's straightforward to do without a macro, in that case


(with-time expr) produces {:time .. :value ..} whereas (with-time :x expr) produces {:time .. :x ..}

Chris Kellendonk00:01:10

I don't know the macro syntax but something like

(defmacro time-with-str
  "Evaluates expr and prints the time it took.  Returns the value of
  {:added "1.0"}
  [my-str expr]
  `(let [start# (. System (nanoTime))
         ret# ~expr]
     (prn (str my-str  " Elapsed time: " (/ (double (- (. System (nanoTime)) start#)) 1000000.0) " msecs"))

Chris Kellendonk00:01:05

This still returns the normal output but lets me use a custom string to mark this specific call


(defmacro time-str [prefix & body] `(let [start# (System/nanoTime) ret# (do [email protected]) time# (- (System/nanoTime) start#)] (println (str ~prefix time#)) ret#))


about the same thing


using prn in this context seems odd, as it just forces awkward quoting of the string part of the output


(. System (nanoTime)) might make sense in the context where clojure.core/time is defined, or might have been the right code when it was implemented, but it's not how we'd normally do interop

Chris Kellendonk00:01:00

That’s good to know. And thanks for the implementation


oh now i see that clojure.core/time was using prn - I guess that' s to make it clearer in the repl that what you are seeing is separate from the return value?

Vincent Cantin06:01:54

Which predicate would return true on a vector, a list, a set or a sorted-set, and false on a map?

Lennart Buit06:01:44

(sequential? ...) maybe

Lennart Buit06:01:56

eh bah, not on set

Lennart Buit06:01:21

I guess your best bet would be to assert that it is seq?, but not map?, I don’t think that all non-mapping collections have a common ancestor. Edit: or is coll? and not associative? is maybe better.

Lennart Buit06:01:21

I guess your best bet would be to assert that it is seq?, but not map?, I don’t think that all non-mapping collections have a common ancestor. Edit: or is coll? and not associative? is maybe better.

Vincent Cantin06:01:50

Okay, thank you.

Lennart Buit06:01:33

Theres also a stack btw, as a collection, it doesn’t have a simple syntax for creating, but it can be useful at times

Lennart Buit06:01:48

(prove me wrong tho!)


Are the semantics of #inst defined at the level of EDN or Clojure syntax?


^ Please ignore. #inst and #uuid are part of EDN.


Are there plans to add more tags in EDN? (Stuff like IP addresses and URLs) I did check out this discussion on google groups about #inst and tagged literals in general:


no plans to add those to core atm


you can of course add any tagged literals you like

Ian Fernandez14:01:18

How I do a validation on a map with prismatic schema that returns the data if the data is correct or empty string if the data is incorrect?

Ian Fernandez14:01:25

I ask on schema's channel?


#schema is probably more appropriate.


can anybody help me with something? I'm trying to read a clojure file and analyze the forms, but it looks like autoresolved keywords can't be read 😞 I'm not sure what to do...


how are you reading it?


the reader has a pluggable system for resolution so it is possible to plug in your own handler there to give it the “namespace context” if needed


i figurred it out 🙂 thx


had to bind the reader-resolver to some NoOp impl of a LispReader$Resolver


i guess that's what you mean alex


I keep getting this at various times:


SLF4J: Failed to load class "org.slf4j.impl.staticloggerbinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See  for further details.


This isn't anything I'm depending on directly... presumably something else I'm depending on is


not sure if I should just ignore it or address it in my project.clj somehow, or what


it's red, that's never good


SLF4J is a logging API with pluggable impls


many Java libraries use it


I'm using a JGit wrapper, that's my first suspicion


what it means is that one of those libs wrote a log statement, and no log impl was found, so it’s using the default (which does nothing)


yeah, jgit uses it


and since I'm not logging anything, /shrug


you can add an additional dependency on one of the explicit slf4j impls and then use that to configure the logging


if you want the warning to go away


I get similar errors when I boot up CIDER on an empty lein project


I see that exists.... if I include it, what else would I need to do?


well, that will only deepen your problems :) tools.logging is also a pluggable logging api.


you can plug slf4j in underneath it though :)


You can include the dep org.slf4j/slf4j-nop to explicitly tell it to not do anything


Thanks, Alex. I'll try that tonight when I'm at home


that's.... not something I would have thought of 🙂 thanks Alex


(I am tickled by having the option of choosing a beta version of no-op)


choose your favorite vintage :)

Lennart Buit20:01:00

this is one of those great tragedies of software right, there where once too many logging frameworks. Now there are too many logging framework frameworks

Lennart Buit20:01:41

yeah but then one meta level higher


🙂 true that.


everything about Java logging should be set on fire


but how would I log that I did it

Lennart Buit20:01:29

this is a problem that seems to plague the java ecosystem most

Lennart Buit20:01:39

how did other platforms deal with it


Python has a built-in logging library that seem to be well-known enough and good enough that most people simply use it. I wouldn't be surprised if there are a few various implementations from years ago that are effectively "dead" now because of that.

Eccentric J21:01:24

Oops I totally missed the “built-in” part 😔


also logging is something that is cross-cutting - needed at many levels, and its users expect to apply a single solution across libraries


so if something usable isn't in the default setup built in, you end up with lots of hacky attempts at modularity and compatibility and "dependency injection" that make the whole thing harder to understand or use properly

Lennart Buit21:01:21

right, I must admit that I always use timbre in clojure. And most libs of my comp also use timbre. So basically, if something doesn’t its part of the problem


The other nice thing about Timbre -- and some of its satellite libraries -- is that you can "hijack" pretty much every Java logging library and force them all through Timbre, giving you centralized control.

Lennart Buit21:01:35

yeah, was looking into that. Can you do it the other way around tho, or is it unwise to depend on Timbre if you publish a lib


Well... Timbre pulls in a bunch of other dependencies from the same author... and that has often bothered me enough to want to switch to something else...


...but whenever I've tried, the pain of logging usually makes me go back to Timbre 🙂

Lennart Buit21:01:34

So I added that bridge thing, slf4j-timbre, and now some java dep decided to DEBUG spam, do perhaps know how to tell timbre to drop everything below INFO from external deps?


timbre/set-level! -- needs to be called before those other libraries get up and running. I tend to have that in my main namespace as a top-level call.

Lennart Buit21:01:41

yeah, but that also silences my own debugs, no?


You can also blacklist packages/namespaces -- see


For example (from our code at work):

(taoensso.timbre/merge-config! {:ns-blacklist ["com.eclipse.*"
                                  :level :debug})

Lennart Buit21:01:42

Yeah, but thats a blanket ban, not level based. Well, I think I’ll learn to live with not having debug

Lennart Buit21:01:51

OH, you can pass a level


No, that sets the level to debug but blacklists those packages.


By default, we set the level to info.


We have

(timbre/set-level! :info)
as a top-level form, immediately after the ns form in our main namespace -- to suppress any/all debug/trace stuff at startup, then we blacklist stuff we're not interested and go back to debug level if needed in dev/test.


I don't believe you can set different levels for different packages/namespaces...?

Lennart Buit21:01:06

Right, its the kafka library thats very spammy, but luckily for me in a particular package only.

Lennart Buit21:01:16

So I’ll just blacklist that

Lennart Buit22:01:21

So, it turns out that you can write a custom middleware function to achieve such a feat


I think it's reasonable for a library to depend on tools.logging and then users can do what they want with it -- including using Timbre to control everything.

Lennart Buit21:01:03

Right, that makes sense

Lennart Buit21:01:25

… added slf4j-timbre to my project, now I get spammed with debug info of one of its libs


I’m back on the clojure wagon for a bit. Just got my vs-code set up with calva, and worked through the 4th chapter of Brave and True. It uses Lein - and I still don’t fully understand what the bounds of that are. When I start lein repl, it’s giving me a `Warning: implicit middleware found: cider-nrepl.plugin/middleware Please declare all middleware in :middleware as implicit loading is deprecated.` - is that something I should resolve, or ignore for now?


sounds like something the CIDER devs need to fix - or may have fixed in a newer version


@wmichaelshirk do you have an old project.clj or something with cider-nrepl in it? If you are just starting lein repl there should not be any CIDER deps in it at all.


I had an ancient profiles.clj in my home directory when I started yesterday. I didn’t know what it did, but it was causing problems. I just deleted everything in it. That got my lein repl working - though with a warning that my profiles.clj was invalid. I was still having trouble getting running with calva (clojure extention for vs code), and it was suggested to me to copy this in: `


{:user {:plugins [[cider/cider-nrepl "0.20.0-SNAPSHOT"]
                  #_[lein-figwheel "0.5.19-SNAPSHOT"]]
        :dependencies [#_[cider/piggieback "0.3.10"]
                       [nrepl "0.5.3"]
                       #_[figwheel-sidecar "0.5.19-SNAPSHOT"]]
        :repl-options {:nrepl-middleware [#_cider.piggieback/wrap-cljs-repl]}}}


That worked to get everything working.


ok. and what is your version of lein?


ok that's the most recent one


is it still saying your profiles.clj is invalid?


No - it’s accepting that fine now.


ah so is your issue resolved?


in terms of everything appearing to work - yes. 😉 Just wondering if this lein warning is something to be concerned about


one last thing is that there's been a migration from tools.nrepl to nrepl/nrepl. and they clash. perhaps some of your deps have a dep on the older tools.nrepl


you can run lein deps :tree to see what deps are required and why


or lein deps :plugins-tree if you need to check plugin deps


grepping nrepl, I get

[cider/cider-nrepl "0.20.0-20190108.170816-9"]
 [nrepl "0.5.3"]
   [nrepl/bencode "1.0.0"]


as these aren't project deps


same thing, but with an :exclusions [[org.clojure/clojure]] on [nrepl


sorry not project.clj, i mean profiles.clj


the version of CIDER that Calva would recommend is likely older than the one that makes the latest lein happy


Are transducers commonly used in clojure?

Vincent Cantin03:01:15

@joshlemer In case you are learning about them, I may suggest you to take a look at this transducer blog post serie and its exercises.

Vincent Cantin03:01:47

I hope it helps.


@josh_tackett We've used clj-webdriver for years but it is no longer maintained. I've been looking at switching to Etaoin but haven't had the time to investigate it fully yet. I had not heard of that other one.


@joshlemer Define "commonly". I think they are being used more and more these days but I'm not sure I'd say they were "common" yet.


It can take a while before new features are really internalized by developers at large and become "the norm". We're only recently seeing "common" usage of the Socket REPL that was introduced in Clojure 1.8, for example, and people are still asking lots of questions about clojure.spec introduced in 1.9.


I think transducers are great -- but they can take a bit of getting your head around -- and a lot of material out there about Clojure was written before they were added so folks aren't as widely exposed to them yet as I think they will/should be.


@seancorfield I'm in the exact same position 🙂 Here are some notes I made about switching. Hope they are helpful: clj-webdriver to Etaoin - to -> go - current-url -> get-url - wait -> wait-visible - input -> fill-human - element & click -> query & click-el


We've started using HtmlUnit for some newer applications -- and nearly everything we have clj-webdriver tests for is legacy and will be retired (this year) -- so we must stick with HtmlUnit going forward rather than convert the legacy tests and/or take on a new Selenium library.


hello, I think I'm confused on how to bring in libraries. I want to use exponential math so am trying to bring in the math.numeric-tower library like so:

(ns armstrong-numbers
  (:require [clojure.math.numeric-tower :as math]))
but I keep getting an error.


I get the same error when I change the dash to an underscore.



Caused by
   Could not locate clojure/math/numeric_tower__init.class,
   clojure/math/numeric_tower.clj or clojure/math/numeric_tower.cljc
   on classpath. Please check that namespaces with dashes use
   underscores in the Clojure file name.


what are you doing to add that library to your project?


it doesn't come with clojure


hmmm. I was just trying to follow along with this:


Do I need to put it in my project.clj dependencies?


that would be the standard way to do it if you are using lein, yes


what is the idiomatic way to do exponeniation (ex 3 ^ 3) in clojure?


user=> (Math/pow 3 3)


that's what comes with the vm at least


ahhh, ok, I think I had found that first. Math/pow is a java thing right?


I think numeric tower tries harder to use precise types


So, as I understand so far, clojure.spec and functions pre- and post-conditions server similar purposes (typechecking at runtime). Is clojure.spec supposed to replace the latter? Or is there something I'm not understanding about their usage?


if you review, that has the standard things like pow, abs, floor, ceil, cos, sin, sqrt etc. etc.


so what do I put in dependencies for the numeric tower? [clojure/math/numeric_tower "0.0.5"]?


@pberganza10 just definign a spec isn't enough to make it get checked, you can use spec checks in a :pre or :post, and you can explicitly turn on checking for a specced function


Ahhh. Think I got it. But what do you mean by you can explicitly turn on checking for a specced function?

noisesmith23:01:22 if you don't turn on instrumentation, the specs you declare aren't checked


(unless you manually check things inline)


Got it! Thanks a lot ❤️


(at work, I've dealt with code that was specced incorrectly, and there was no indication that it was because no code path actually ever checked args)


@pberganza10 instrumentation and checking are good for development, but spec can also be used explicitly in your code for production use via s/conform and s/valid?


We use spec very heavily at work, both in our development/test work and also in our production code for validation of data structures (such as API inputs).


Ok so spec has a much general use-case than I thought. I guess I could compare it to schema validation on other languages (e.g. Marshmallow in Python)?. So pre- and post-conditions are exclusively used for feedback during development,?


@chase-lambert I think the article you linked had a link to the numeric tower project, that will tell you the right way


it's probably more like [org.clojure/math.numeric-tower "..."]


yup, too obvious. sorry about that


there was a link right to the github at the top


yeah, and the github shows the dep vector to use