Fork me on GitHub

@markw you can drop the apply in url-encode


oops - yeah you're totally right. Had that in there on an earlier version where I hadn't called str/join yet


Is there a special way to package a library so as to leave out the clojure version within leiningen?


yes, the normal uberjar process does that


if you are getting a clojure version you don't expect packaged, you should check the output of lein tree :deps, likely some dependency is pulling in another version


a lein project doesn't come with clojure by default, either you have to depend on, or you get whatever random version one of your dependencies pulls in


Oh, I mean is there a special way to package libraries so as to leave out clojure, but keep it around for development? From what you describe, you don't need to?


ah, I won't worry about it for now 🙂


Alright, i'm doing my social media rounds


@benzap When libraries are published to Clojars, they only have the library code -- users run tools that bring in all the dependencies. Is that what you want? Or some middle ground between JARs and uberjars?


@seancorfield Thanks, that clears things up


@seancorfield that would probably include the generated pom.xml right? But not the project.clj itself?


will lein uberjar compile .java files before attempting to compile .clj files (assuming aot is on)? For some reason, I have src/java files that work fine when running a repl, but during lein uberjar it claims it can't find the java classes on the classpath.


explicitly adding "javac" to the :uberjar :prep-tasks solved it


Hello! Quick question: is there a standard way in clojure to attach test-cases to functions? So as to be able to list all the test cases related to a specific function


I know I could do this myself through metadata


but I am wondering if there is a standard approach


interesting.. it should be possible to introspect the test-code to see which functions it calls.. there should be a Leiningen plugin for that, no? 🙂


If I need to parse a string representing a number in clojure, is it generally the best idea to parse it as a java Long instead of an Int even if I know it will be java int sized? since it pretty much will be promoted to Long if I do anything with it anyway?

Alex Miller (Clojure team)14:04:20

yes, parse it as a long

✔️ 4

Makes me sad when I'm using Java interop and the Java function requires an Int so I have to manually coerce my Clojure number to Int as part of the call

👍 4

@hmaurer I just ran across a macro to do this that I was surprised to find. Was it in clojure.test?


Yes, with-test, e.g. (with-test (defn foo [] 42) (is (= 42 (foo))) ...)


oh wow, interesting


thank you!


I've always been fond of tests appearing with the code itself, and have never been sure why nobody likes this idea.

Alex Miller (Clojure team)14:04:33

@eraserhd I believe clojure.test already does this - you can attach test functions with :test meta in a defn and it will find and run them

Alex Miller (Clojure team)14:04:55

user=> (require '[clojure.test :refer :all])
user=> (defn ^{:test (fn [] (is (= 0 1)))} foo [] (println "hi"))
user=> (run-tests)

Testing user

FAIL in (foo) (NO_SOURCE_FILE:7)
expected: (= 0 1)
  actual: (not (= 0 1))

Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
{:test 1, :pass 0, :fail 1, :error 0, :type :summary}


yeah you can implement and use all those structures in Clojure but you don't have a proof engine checking your work so their power to weight ratio isn't as good.


My experience agrees with @arrdem's here. Without types, there is almost always a less verbose way to do these things. e.g. some kind of threading operator instead of a monad instance. In a typed language, the implementation is selected based on the type, and it isn't so verbose.


I mean, you don’t really have that in haskell either, the monad laws are satisfied by most monads by convention rather than formally verified


the reason why using monads/cat theory concepts in clojure doesn’t map too well is, IMO, not because of the lack of a type system, but because of the fact that in clojure we don’t create new types/categories for abstractions, we reuse what we already have, and what we already have already has monadic operators defined in the language


I’ve been writing ocaml for 6 months now and IME monadic structures don’t emerge because of the type system, they emerge because I’m creating new types all the time (which are 2 orthogonal things)


the types in Haskell absolutely do reduce boilerplate when it comes to stuff like monads, applicative, etc.--just because you can’t prove the monad laws via the type system doesn’t mean that the type system isn’t providing a ton of assistance in making it far simpler to implement and use those kinds of algebraic structures in Haskell vs. Clojure, where everything has to be manipulated on the value level, and where libraries like those (IMHO) are mostly useless as a tool to simplify how you structure computations


that doesn’t mean monadic structures don’t exist in Clojure, just that you can’t use the type system to express anything about them


I mean, @bronsa I think we are saying the same thing, in part, but I do think it’s important to acknowledge that the type system does play a part here


or, lack thereof


>just because you can’t prove the monad laws via the type system doesn’t mean that the type system isn’t providing a ton of assistance absolutely, I was stating the opposite tho, having a type system helps but doesn’t cause the emergence of the pattern, it’s having tons of types that helps the monadic pattern emerge


ah okay, apologies if I misunderstood


i.e. I’m arguing that the causality link for the emergence/usefulness of monadic pattern is a coding style that emphasises the creation of ad-hoc types, and having or not a type system is an orthogonal issue (it clearly helps a ton and promotes the usage of monadic patterns, but it doesn’t cause the emergence of those patterns)

😲 4

what do you mean by “…a coding style that emphasizes the creation of ad-hoc types…” ?


in clojure we don’t create an ADT for whatever


we just reuse a vector or a map


we already have tons of tools to manipulate those


if we did create tons of different types/data structures I’m sure we’d see the emergence of monadic protocols in clojure too


ah okay, so you were more talking about Haskell when you wrote that


s/haskell/any language focused on types/


I think it’s the same for ocaml, altho the lack of typeclasses makes it a bit less common than in haskell


right, although isn’t the lack of purity in OCaml and other ML-family languages a confounding factor there too?


in any case, I don’t disagree


no I don’t think so


it’s just that functors are significantly more heavyweight to use than typeclasses so it’s a bit harder to express a polymorphic bind for example


so what usually ends up happening is that in ocaml one just creates monomorphic ad-hoc monadic operators for whatever module they’re defining


back to Clojure, the way I’ve always thought about it is: in Clojure these monadic structures already exist, but they are subsumed in the “one-off”/ad-hoc constructs we get to deal with various operations that would be handled by a monadic value in Haskell. Stuff like state manipulation, IO, etc. I suppose one could say that for any imperative language though


but it also suggests to me that these kinds of libraries awkwardly encoding a bunch of algebraic structures on the (mostly) value level are of dubious utility


(clearly “ad-hoc” is the word of the day)


is 22MB a normal size for lein uberjar output’s standalone version? I’ve got 1 single clj file that is just under 50 LoC


This depends on your dependencies. You can open the jar and look whats inside.


looks like clojurescript is taking quite a bit


since I don’t need it in production, I guess I can exclude it from uberjar right?


If you are sure that is the case, you can do that. It depends on your build tool how to do that.


lein deps :tree also shows you the complete dependency tree.


Oh interesting. Most of our uberjars are similarly big for small scripts but I'd not considered that it'd be pulling in ClojureScript


I stripped out clojurescript and reagent and now it’s just under 5MB

👍 8

You know, I'd like to get a feel for what people feel are "big" or "small" clojure projects.


Like, for me, I did a 8,500 line Clojure system, 35% test code, and thought that was kind of mediumish. I'm working on a 13,500 system, with Clojure and ClojureScript, and it seems absolutely huge unwieldy.


And I think of 500 or 600 lines as a medium sized library.

Alex Miller (Clojure team)17:04:06

there are a number of Clojure code bases I’m aware of in the 50k+ range and a few in the 100k+ range


Do people think of them as big or hard to deal with?


tbh 100k of clojure code easily compares to a 1MM+ java project, and they are also rare


I been working in 50k+ clojure code bases for several years now. my first clojure job had much less than that when I started, and and had blown past it several years before I had to find a second clojure job, that I am pretty sure was past that when I started (a little more than a year ago)


what are y'all using to measure loc ? i've got an ~80kloc codebase by a simple measure, and it doesn't seem unwieldy

👍 4

@hiredman Ok, so when does a project typically feel "big".. Sluggish, hard to change.


When stuff got complected?

👍 4

I am not sure you can directly compare like that


I use find src test dev -name '*.clj*' -o -name '*.edn' |xargs wc -l.


Well, if there's no pattern, and it's solely about design, that would be a thing to learn.


I think that's probably true.


ha, quite similar to mine: find . -name \*.clj -o -name \*.cljs -o -name \*.cljc | grep /\*/src/ | xargs cat | grep "^.*\S.*$" | grep -v "^\s*;.*$" | wc


one of our projects is 54kloc clojurescript


the first 50k+ code base left me wanting something with a clearer more defined module structure, so I use component as a basis for everything now


the first project had a kind of home grown module system, but it was built around global state (mostly def'ed atoms), which ultimately made testing and reusing code fraught


Back when I was building hobby systems in clojure, I recall that things can quickly start to feel "too big" when I was using state management methods that made things too complex


we use multiple modules, a component system and a hexagonal architecture pattern... it seems to scale very well


Weirdly, I suspect component makes things worse. We have a tangled set of dependencies and the system is awkward to boot for tests.


I'd say the first instinct of most is to organize code in some kind of taxonomy tree embodied in the file system. which can sort of kind of work, but you run into the common issue with taxonomies, of things not fitting cleanly one place or another


hexagonal would be very nice, I think 😄


Nowdays there's lots of workflows for keeping large systems sane


Tests are always awkward if they depend on IO, imo. Almost every project I've worked on has a pile of macros, configs that you have to cargo-cult to get a new test implemented. Component systems help keep it sane, but it's always awkward.


larger systems also require a different mental discipline to ignore the parts you aren't working on

🙈 4

I am curious: does anyone here have a story to tell / an opinion on Clojure as a language for domain modelling, in comparison to, say, Haskell?


I don't have much experience with Haskell, but can you get any more flexible for domain modeling, in a mapable and reducible way, than with clojure's maps?


I guess if your model is a rule system, a type system would be more efficient

Alex Miller (Clojure team)17:04:32

I find in general, Clojure code is almost always amenable to being made smaller with the application of time and effort

👍 4
Alex Miller (Clojure team)17:04:51

and in some sense I appreciate having the choice about where and when I choose to work on that

Alex Miller (Clojure team)17:04:31

the key here being that improving abstractions in Clojure generally makes code smaller. Improving abstractions in Java generally makes code larger (by adding additional interfaces etc)


when using cognitect.transit/write, is there a way to produce a transit value? Or do you have to write to a ByteArrayOutputStream?


On the cljs side I see you can just do (writer :json), but on the clj side you need a (writer out :json)


@datran there's no such thing as a "transit value"


you want a string, right?


It looks like a vector in my repl, but I can believe it's actually a string


I have no idea what kind of value you are talking about


transit is a way to encode clojure data into bytes


in cljs, you don't deal with bytes directly and instead you get strings


oh, okay, that makes sense


(which I think is JSON in practice, right?)


the reason it gives you bytes is if you used a string, you'd still make some conversion into bytes to send the data to someone else (or store it)


so it's actually more direct to just get bytes for the common case


@ddellacosta that's configurable, edn and messagepack are also supported


the default is edn iirc


Okay, so on the server I can just turn it into bytes and the client will interpret that as a string


@datran you may just want the String constructor (String. some-byte-array)


@datran well it depends on how good your ipc is - it might hide the transport from you and need to get a string


or if you're lucky, it can accept a byte array or an InputStream


I'm pushing edn back and forth across a websocket using transit. So on the client I'm writing (t/write (t/writer :json) {:msg "hey"}) and on the server I'm translating that back into edn with (t/read (t/reader (ByteArrayInputStream. (.getBytes data)) :json)))


Now I just need to complete the round trip by pushing it back into bytes and sending that across.


You've helped clear up a fundamental misunderstanding I had, so thanks for that


you might want to check what kind of data your websocket library can provide or accept - you mightbe able to make transit write directly to the socket for example


or on the back end read, read directly from the socket


all that said, the various byte-array / input-stream / output-stream / reader / writer / string conversions are actually pretty cheap - the apis are kind of annoying but they make sense once you take it all in


but transit defaults to the lower level case, I assume for the situations where data transfer is in a hot path and you can't afford the extra abstraction


I usually call toString on the bytes from clj before sending over socket to read in cljs. Maybe not necessary?


probably not - depends on what your socket library knows how to use


in fact you could probablymake transit write directly to the socket and skip creating the byte array - not that you neccessarily want to, but it would probably work


@ajs if you think about how most socket stuff is working under the hood, the common pattern ends up with clojure value -> output stream -> bytes -> string -> bytes -> output stream -> client


when really in theory (with the right socket api) you could just be doing clojure value -> output stream -> client


I just follow examples I see since the lower level stuff isn't clear on specifics.


(that's a simplification since an OS level api that java doesn't let you use directly treats the output stream as bytes on both ends of the network etc. of course)


@ajs and that's fine - if the abstraction works and keeps things simple enough for you to use it effectively and it isn't a performance problem (it's unlikely to be) you can continue as is


For example @dnolen has a client server transit example repo for Ajax so I just follow that process in the absence of anything more enlightening


the reason I started rambling on this topic was because of the question "how do I get transit values from this byte array" which opens up the question of how transit is actually meant to be used etc.


but if converting to string makes your code comprehensible, that's fine, go with it


The lines between transit, bytes, text, json, and edn are a bit vague in most tutorials or examples.


also there's a lot of imprecision in the conversation around that stuff - for example when it's suggested above that somone is getting edn out of transit - likely what was actually meant was plain clojure data of the same types supported by edn, since transit is an alternative to edn (which optionally uses edn, but that shouldn't matter beyond a config switch in your code)


When you print transit it doesn't look like bytes, it's readable, just not as readable as json, which further confuses, is it text? Is it bytes? Questions without answers on most sites.

Alex Miller (Clojure team)18:04:58

transit is a json string (which is an encoding of bytes)


@ajs the idea of "printing transit" is a bit sloppy though - you probably mean a string made out of the outputstream written to by transit


or on the frontend, the string it outputs directly (I keep being jvm centric..)


Like with protobuf I know I'm dealing with bytes. No gray area. The socket requires an array buffer. But transit uses a byte stream but isn't really bytes in that way.


perhaps what you want is a tutorial on bytes, outputstreams, inputstreams, and strings on the jvm?


I learned that stuff by googling and finding stack overflow answers about how to turn an output stream into an input stream or a byte array etc. etc. and converting the result into interop - I wonder if there's a good blog post or something on this


That would be a worthy read. I nominate you.


hahaha I'll seriously consider it


it's interesting, in c all those things would just be arrays, in js all of those things would just be strings, but in these other languages with more nuanced abstractions we end up on all these variations and conversions between...


time to start writing




I'm a little confused about Korma and was wondering if anyone can help? Is there a way for Korma automatically create the DB for me or do I have to create the SQL scheme seperately?

sveri18:04:04 IIRC you have to do that yourself. There are a few migration libraries for clojure that will handle that for you. Regarding koma I would advise you not to use it as it is a bit to limiting. I stick to directly.


Okay which libraries are those?


And also is there any good reference for the difference between entities, entity-fields and the such? All I want is a simple database mapping users to positional entities which contain coordinates, speed, direction, and a timestamp.


Walkable is a new library that can help you with such "mapping" (sql term is JOIN)


I'm obviously not very well versed with SQL.


Hm, I see. I dont use any of them myself as I find it easier to handle SQL directly instead of working with an abstraction over it. I would head over to and search for migrations

myguidingstar19:04:58 the Duct framework provides a very nice enviroment to explore sql yourself


Thanks @myguidingstar that is really helpful.


question about :aot :all when I run lein uberjar -- sometimes when I do the clean and uberjar build, it logs every namespace as it gets compiled. Other times, it will only show maybe 3 namespaces with the "Compiling..." log. Why would this be? Is it cached builds for those namespaces?