Fork me on GitHub

Thanks a lot for all the insights, sean!


Is clojure.core/merge supposed to be used with non-maps, please? It's documented for maps as merging and replacing repeated keys with the last (rightmost) present value. For non-maps it seems consistent but non-obvious: (merge [1] [2 3] [4 5]) evaluates to [1 [2 3] [4 5]]. Wouldn't you expect [1 2 3 4 5]? Admittedly, unsure what I'd expect with sequences, as: (merge '(1) [2 3] [4 5]) gives ([4 5] [2 3] 1), (merge '(1) '(2 3) '(4 5)) gives ((4 5) (2 3) 1).


Ah, that would make it like concat. Hence the difference. But what's the meaning/goal of merge with sequences?


Likely nothing, quite a few core functions assume the happy path.

Alex Miller (Clojure team)00:09:38

Vectors are keyed by index

Alex Miller (Clojure team)00:09:19

But merge works as if by repeated conj iirc what the docstring says


Does anyone have recommendations of github reagent tutorials? I owuld prefer samples of many mini projects that I can use as starting ground for my apps. It seems that the tooling and library integration is hardest to me.


Is there anything like Spring for Clojure? I need a IOC Container so that I can inject all dependencies (db, logger) into my backend api.


@grierson people typically use something like Component of Integrant for this


@grierson don’t know if this is exactly the same use case, I skipped the whole Spring thing


@grierson also mount, for something a little bit easier to get started with.


@grierson it depends what you want to do, limunus is comparable to spring boot, let's you start quickly


how might i go about reading and writing to/from a file in the same directory as my uberjar? i need to read, store, and update some simple config that's generated at runtime.


For reading, io/resource should work.


hmm. i can spit/slurp from outside the jar, but the file paths are relative to the directory from which i've run the command to launch the jar. i think i can solve that by supplying some shell scripts to launch the app.


@joshkh (System/getProperty "user.dir") gives you the directory that the app is running from


I was just casually strolling through the leiningen ring plugin source code and found this: (if (#{:all [:all]} aot-list) ...) can someone explain to me what #{:all [:all]} does? I know it creates a set of a keyword and a vector of the same keyword, but what does it do in the if?


sets are also functions. when called with an argument they return the argument only if it's present in the set. in other words, "does this set contain the thing i'm passing to it?"

(#{:a :b :c} :a)
=> :a
(#{:a :b :c} :d)
=> nil
(some? (#{:a :b :c} :a))
=> true


the last example being the truthiness behind the if


@azzurite other data structures are also functions. for example, map this map over a vector of keywords, which are also functions:

(map {:a 1 :b 2 :c 3} [:a :b :c]) => (1 2 3)


to answer your question directly, do the true thing if aot-list is equal to either :all or [:all]


Okay I just think I got confused because aot-list is weirdly named then, as it's not necessarily a list


agreed. it'd have to be a vector of one thing. i've run into situations in which i collect values that under certain circumstances end up being a list of one, so i can understand. like using (cond-> [] ...) to conj some configuration.


@azzurite :aot-list is normally a vector of the namespaces you want lein to compile "ahead of time", e.g., [some.namespace some.other.namespace ..] but there's a special value of :all meaning "compile everything". However, some folks mistakenly wrapped it in a vector [:all] so lein is just allowing both forms here.


(and :aot-list can be just a single namespace anyway :aot program.core)


Again, for convenience so you can omit the [ .. ] when you only want one namespace compiled, instead of being forced to write :aot [program.core]


that makes sense, thanks everyone


I'm using ring/compojure for the first time and I'm a little confused about middleware. Is it just for altering the request/response or can it be used to return a response? For example, I have to validate a payload before it's converted to edn. I'm currently using the wrap-json-body ring middleware to convert the payload to edn. Can I create middleware that validates the payload before the wrap-json-body middleware runs, but if it's not valid, return a response from the validate middleware and short circuit the pipeline?


I suppose I could write a middleware function that validates the request and adds a flag to the request to say if it's invalid, so the handler can check this and return an appropriate response? I was initially confused because I was thinking the middleware should return a response if it's invalid, but that's not the responsibility of middleware afaik.


(fn [handler] (fn [req] (if (something req) (handler req) {:status 500 :body "error"})) something like that


ohhh, that makes sense. Thanks!


@brandon.ringe you can also enhance the response that some other handler returned:

(fn [handler] (fn [req] (let [resp (handler req)] (assoc resp :body "altered body"))))

👍 4

Hi, I have a question about web apps, coming from the python world. In python, the parallelism and async request handling is apparent - you are pretty much required to run your app with an async app server (gunicorn, uwsgi...). I'm using http-kit for websockets, which shows you can do 600k (!) connections - . Clojure has way (way) more first class support for async stuff, so where is that parallel/async stuff in the stack? Is it enough to say "http-kit is handling it, don't worry about it"? Should I be using some java application server (tomcat, jboss, etc)? I'm just not clear exactly where the parallelism is in the http-kit stack (if you can even call it a stack...). Thanks very much in advance for any answers, or links to where I can just read this stuff for myself.


Http-kit is your "async app server". I mean it says on the main site itself: "HTTP Kit is a ... HTTP .../server for Clojure.


It uses ... to support highly concurrent a/synchronous web applications."


ha, yes - gotcha. I guess I mean - that's all i need?


there's no extra infrastructure necessary? nginx in front?


If you want to run web apps, yeah


Depends on your environment


It just serves your site on a port


cool - just a little jarring coming from python, where that's a decision you have to make (how to support more than one req at a time)


If that is all you need, then you're good to go


do all clj app servers behave the same way? do they handle each request in a Thread? sorry for the simple questions, i haven't gotten the proper google query together to find exactly what i'm looking for


There is no server that only handles one request at a time


It seems insane that that even seems to exist in python


ok - great. thanks for the help! much appreciated. have a good night! (or whatever time of day it is where you are...)


Actually I have to correct myself - I'm sure there are servers that only handle one request at a time or can be configured to do so. But they are either not used or it's not the default.