Fork me on GitHub

Hi! Is there a way to add metada to a final Java class? I need to have different cheshire formatters for different instances of a Java class (backwards compatibility).


You can't add metadata to arbitrary Java objects. Only to things that implement clojure.lang.IObj


@seancorfield Thanks for the explanation. I've tried using proxy but that didn't work.


(defn wrap-money
    ([^Money m] (wrap-money m {}))
    ([^Money m _meta]
     (proxy [Money IObj] [(.getAmount m)]
       (meta [] _meta)
       (withMeta [meta'] (wrap-money m meta')))))  


Even if I create a Java wrapper that implements IObj, it's not gonna work because the Money class is final.


There's another interface you need to implement as well, forgot what it is


IMeta maybe?


@didibus will try that, thanks


nope, same error Cannot inherit from final class


Oh, that's different, you can't extend a final class in Java


I'm guessing Money is final?


All you could do is use composition, make something take a Money inside itself. MoneyWrapper, you can make that a vector, a map, a record, or go for a deftype or a Java class, up to you


But I'm guessing maybe cheshire has another mechanism to pick its formatter, aside from meta?


@didibus I've spent the last hour reading the cheshire docs & source and, to be honest, I think even the meta route wasn't going to work because I don't think Cheshire will pickup the correct superclass.


I really don't want to have to refactor old code, so I've been trying the polymorphism/meta route before a wrapper container.


Clojure protocols can add functionality to existing classes, I believe even final ones, only for Clojure protocol functions. Not sure whether Cheshire has any protocols you can extend in its implementation


@andy.fingerhut cheshire does have protocols to extend its implementation, but I don't see how I would differentiate one format from another without metada or somehow extending/subclassing the original class. Maybe my OO is a little rusty?


Can you create a wrapper/box class for the special instances and have it contain the money object, then add an encoder for your box class that accesses it?


(require '[cheshire.core :as json]
  '[cheshire.generate :as cg])

(defrecord MyMoney [money])

(cg/add-encoder MyMoney
  (fn [c jsonGenerator]
    (.writeString jsonGenerator (str (.-money c)))))

(json/generate-string {:m1 (MyMoney. 123)})
;;=> "{\"m1\":\"123\"}"
(just replace the str call in the encoder to however ou want to access the money object)


Thanks for the suggestion, that's precisely where I arrived at, was just coming back to report on that 😃


the fact that proxy (understandably) doesn't support final classes crushed my simple workaround, but this is a reasonable alternative.


@U0B7P8YMB I haven't personally done it, but I believe that one of the reasons for creating Clojure protocols is so that you can define protocol functions differently for every class, even for final classes and/or ones that you do not want to change/extend in any way.

👍 8
andy.fingerhut04:04:40 in particular the part about extend

✔️ 4
Adam Helins08:04:40

Using defn, there is no way to attach metadata on the fn itself rather than the var, is there?


the only metadata that is attached to the fn is :tag but you can use

(def foo (with-meta (fn [x] ...) {:k 'v}))
defn is just a macro that expand into ^ that form

Adam Helins11:04:21

Indeed, but it would have been slightly nicer keeping defn . Thanks!


write your own macro )


(defmacro defn* [meta & body]
  (let [[_ name f] (macroexpand (cons 'defn body))]
    (list 'def name (list 'with-meta f meta))))


These will break arglists in most tooling... I'd recommend copying the meta to the fn


tooling should be ok because arglists attached to var not to the function


I misread your trick, interesting


hey everyone, Im seeking general advice regarding writing tests and fixtures lets say Im testing a REST API, specifically a GET /user/123 where 123 is the id of the test user create right before the test by a fixture

(defn create-delete-user [f]

(use-fixtures :each create-delete-user)

(deftest user-test
 (testing "get user bla bla .."
   here I need to compare the result of the HTTP call with the fixture user))
lets say fixture/create-user returns the created user, whats the best way to share this data with the test inside the testing block? I could create an empty atom and write and read there, but this just feels wrong

Darin Douglass18:04:20

you could use a binding instead if you didn't want to use an atom:

(def ^:dynamic *user* nil)

(use-fixtures :each
  (fn [test]
    (with-bindings {#'*user* (fixture/create-user)}


which one is more idiomatic clojure? Im ok with anything, Im just asking because of shared mutable state etc


the idiomatic thing would be to use binding - my understanding was that with-bindings is a helper for macros

Darin Douglass18:04:45

i always forget which func is which, for some reason my eyes gravitated towards with-bindings this time 😛

Darin Douglass18:04:54

imo binding does feel more idiomatic. however, assuming test runs are independent, i typically prefer the "fixtures create/clear tables, while tests setup their data explicitly" route


I could also dont use a fixture to create data and do stuff inside a let block on the test itself, but it feels dirty


thats exactly what I am talking about, to be honest seems the most sane way of doing it


although it feels strange to mix setup code with the actual test, but maybe Im just used to something else and this is fine

Travis Jefferson18:04:45

some pedestal docs I stumbled across yesterday approached this with a purpose-built macro

Travis Jefferson18:04:56

(defmacro with-system
  [[bound-var binding-expr] & body]
  `(let [~bound-var (component/start ~binding-expr)]
         (component/stop ~bound-var)))))

Travis Jefferson18:04:50

you still end up with a let-like syntax in your test, but at least you don’t have to copy the setup/teardown

Darin Douglass18:04:19

(use-fixtures :once
  (fn [test]
    ;; really only needed if your db instance is persistent

(use-fixtures :each
  (fn [test]

(deftest test-something
  (let [user (db/crete-test-user!)]
    (sut/do-a-thing user)))

Darin Douglass18:04:41

imo it all really depends on how much your tests share, how complex the db is, etc


thanks everyone for the input 🙂


Is it possible to get an ISO String formatted date in Clojure without using Java? ie is there a built in for clojure? (iso string):



I don't think Clojure core has a date time API. Just use the one from Java 8 (not the calendar API, use the Local* things).


well, I figured I'd ask anyway, i was having a hard time finding anything in clojure. Thanks


also if clojure had a built in for time, that's what it would do


with few exceptions any domain stuff will not be bundled with clojure itself, only data structure and algorithmic functions are well represented

👍 4
Nicky Chorley20:04:24

(of course it uses java.time underneath


@U011PQGUDCG (str (.toInstant #inst"2000"))


That did it thank you!


java.time is a awesome lib I recommend to use it directly

👍 4

second that. also see my lib to improve the experience with data literals, e.g. #time/instant "2018-07-25T07:10:05.861Z"


If I start a thing in the REPL that is supposed to read from STDIN, how do I send something to it?


by sending something to stdin - or more generally you can bind *in* to an apropriate source of input


clojure's read etc. will use whatever *in* is set to (it can be set dynamically using binding)


when you use a network repl client, *in* will be bound such that read still works (unless other tooling like your editor gets in the way)


of course, be wary of calling read in a background thread while accepting input on the same *in* in the main thread (and visa versa)


Interactivity would be nice, but it's okay if I have to bind *in* to something. Since there is only one Java process now (the REPL's) I was confused who will capture the input. Your answer helps! Thanks.


you don't have to bind *in* if you want to use the same input source as the repl itself, it will just work (unless an editor breaks that...)


Since the REPL is already running, is there a way to "attach" to the stdin now?


the *in* of your repl client is the one that will be used by read, not the one of the server process


how did you start the server? it might be possible to get its stdin, it might not, but it shouldn't matter


That still means I have to dump something in a text file and bind that to *in*. Is there another way?


if you want to read from a text file, that's pretty much how you do it - unless you want to use slurp and read-string instead of read


^ The server is just CIDER jack in.


that's why I mentioned editors


thanks to cider jack in, emacs owns your server's real stdin and I doubt you'll get it back

Ahmed Hassan20:04:47

What difference would it make in the case of cider-connect?


because emacs started the process and connected something to it


maybe there's a way to ask emacs for that file handle and redirect something else to it, but that's not a clojure question any more, it's an emacs / unix question


and I don't expect it to be easy - not compared to binding *in* which already does what one needs here


It seems Emacs can send something to an inferior process and rebind its stdout on the fly to a buffer. But I will experiment with it some other day. (Bottom line: Emacs does everything!)


except for example threads

Ahmed Hassan20:04:12

Emacs is a mini operating system


without threads


I stand corrected


I wonder if this is up to date " quickly shows that Emacs’ threading implementation has many data races, making it"


"only one thread runs at a time"


anyway, this is well off topic by now, sorry


NP. Don't know. Never bothered. I like Emacs because you can be totally off the mouse and some of the things just work. Although the UI is terribly slow as compared to something like VSCode.

Ahmed Hassan21:04:27

@U051SS2EU what alternatives do you suggest to Emacs?


I don't think that's on topic here, I meant the thread thing to be a joke / tease but my knowledge is out of date


use emacs if that's the thing that works for you


Threads in emacs are experimental for now. Packages are advised not to rely on them yet


Most concurrency for now is handled through sub-process


but you shouldn't need it - nothing in clojure relies on the identity of stdin itself, it all uses the *in* abstraction instead

Adam Helins20:04:45

Is there a secret way for aliases to include other aliases in deps ?

Alex Miller (Clojure team)23:04:42

what is your goal? running multiple commands or combining multiple pieces of configuration?

Adam Helins20:05:08

Rather combining multiple pieces of configurations (dependencies, really)

Alex Miller (Clojure team)20:05:53

and invoking multiple aliases at the same time is just more than you want to require of project users?

Alex Miller (Clojure team)20:05:07

just trying to understand the needs

Adam Helins20:05:41

It is just that sometimes (but not that often, I concede) it can become a bit hard to track, what alias should be invoked when

Adam Helins20:05:11

Honestly it is not a big deal, I was curious about it but I would certainly not fight for it...

Alex Miller (Clojure team)21:05:03

we have some new stuff coming soon and so I'm really trying to tease apart whether this would be helped or could be helped

👍 4

@adam678 No. Aliases cannot bundle together other aliases. It's quite a common request.


Might it be fairly straightforward to write a Clojure program that reads a deps.edn file, or something similar to one that introduces some new convention for data that lets one alias reference another one, and merge the contents of the aliases together? Seems like a potentially nifty 3rd-party utility, although definitely understandable if Clojure core team would not want to write/maintain such a thing.


That would open the door to N different tools (or perhaps one that combines N different features) for reading something, and generating a deps.edn file.


I usually add a few bash scripts for common tasks which all have the proper aliases.


heck, you can even add a bin/clj script that does pretty much what you’re saying

Adam Helins21:04:13

Just for info, is it by choice or by constraint? Otherwise yes, custom bash scripts is what I am doing, but it does feel too "smart". Maybe it is for the best...


just bash it – it’s for the best


(famous last words, but srsly tho)


I've just been duplicating for now


Also, while you can't have an alias of alias, you can list out multiple alias when running clj to combine them


clj -A:foo:bar

Adam Helins21:04:20

Oh yeah, by custom bash scripts this is what I meant, so that I don't have to type long chains of aliases combinaisons


Ya, you can just setup a bash alias for that command


I think that's fine


I even have some bash alias for single alias. Like I've remapped cljto clj -A:repl


I'd like to run clojurescript tests using kaocha-cljs. So I put the [lambdaisland/kaocha-cljs "0.0-71"] dependency in my lein project.clj, and restart the repl and run the command in the root directory:

clojure -m kaocha.runner unit-cljs
But I get the error:
Execution error (FileNotFoundException) at clojure.main/main (
Could not locate kaocha/runner__init.class, kaocha/runner.clj or kaocha/runner.cljc on classpath.
Why would this be, and how can I fix this?


clojure doesn't use project.clj


you probably want the koacha lein plugin, assuming such a thing exists


why does kaocha-cljs exist then if you could just use kaocha for running cljs tests?


never mind, you are using koacha-cljs not koacha, and that doesn't use lein


it looks like you would need to migrate away from lein to use koacha-cljs, or port it to lein somehow


so I'm using the Luminus template, and I haven't yet needed to worry about the connection between cljs and clojure. But any cljs dependency I put in the project.clj dependencies and it just works.


sure, that's how the lein integration works


but koacha-cljs is built around clj/clojure which is a different tool, not compatible with lein


how to port kaocha-cljs to lein


lein run kaocha.runner unit-cljs should work


@souenzzo that gives me this error:

.BindException: Address already in use
	at .bind0(Native Method)
	at .bind(
	at .bind(
	at .ServerSocketChannelImpl.bind(
	at io.netty.bootstrap.AbstractBootstrap$
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(
	at io.netty.util.concurrent.SingleThreadEventExecutor$
Syntax error (BindException) compiling at (/private/var/folders/zz/zyxvpxvq6csfxvn_n0000000000000/T/form-init6496307984697349116.clj:1:125).
Address already in use

Full report at:
and I also tried in the clj repl:
(require '[kaocha.runner])
user> (kaocha.runner unit-cljs)
Syntax error (ClassNotFoundException) compiling at (*cider-repl luminus/vendo:localhost:63551(clj)*:62:7).


the lein command line would translate to (koacha.runner/-main "unit-cljs")


Still, I get 1. Unhandled java.lang.ClassNotFoundException koacha.runner 382 69 clojure.lang.DynamicClassLoader/findClass 418 java.lang.ClassLoader/loadClass 77 clojure.lang.DynamicClassLoader/loadClass 351 java.lang.ClassLoader/loadClass -2 java.lang.Class/forName0 348 java.lang.Class/forName 2211 clojure.lang.RT/classForName 2224 clojure.lang.RT/classForNameNonLoading 1041 clojure.lang.Compiler$HostExpr/maybeClass 7045 clojure.lang.Compiler/macroexpand1 7075 clojure.lang.Compiler/macroexpand 7161 clojure.lang.Compiler/eval 7132 clojure.lang.Compiler/eval core.clj: 3214 clojure.core/eval core.clj: 3210 clojure.core/eval interruptible_eval.clj: 91 nrepl.middleware.interruptible-eval/evaluate/fn main.clj: 437 clojure.main/repl/read-eval-print/fn main.clj: 437 clojure.main/repl/read-eval-print main.clj: 458 clojure.main/repl/fn main.clj: 458 clojure.main/repl main.clj: 368 clojure.main/repl 137 clojure.lang.RestFn/applyTo core.clj: 665 clojure.core/apply core.clj: 660 clojure.core/apply regrow.clj: 18 refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn 1523 clojure.lang.RestFn/invoke interruptible_eval.clj: 84 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 56 nrepl.middleware.interruptible-eval/evaluate interruptible_eval.clj: 155 nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn 22 clojure.lang.AFn/run session.clj: 190 nrepl.middleware.session/session-exec/main-loop/fn session.clj: 189 nrepl.middleware.session/session-exec/main-loop 22 clojure.lang.AFn/run 748 java.lang.Thread/run


you still need to require koacha.runner , and it needs to be available as a dep you can require


that error is saying it hasn't been loaded


user> (require 'kaocha.runner) nil user> (koacha.runner/-main "unit-cljs") Execution error (ClassNotFoundException) at ( koacha.runner


And my project.clj dependency contains both Kaocha and kaocha-cljs


so why classnotfoundexception?