Fork me on GitHub
#beginners
<
2018-09-22
>
polymeris00:09:21

Thanks a lot for all the insights, sean!

peter-kehl00:09:38

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).

peter-kehl00:09:35

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

frenata00:09:08

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

awb9907:09:11

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.

grierson11:09:33

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.

borkdude11:09:22

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

borkdude11:09:54

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

orestis13:09:43

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

gklijs16:09:19

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

joshkh16:09:31

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.

orestis16:09:08

For reading, io/resource should work.

joshkh16:09:51

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.

borkdude17:09:14

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

Azzurite17:09:51

I was just casually strolling through the leiningen ring plugin source code and found this: https://github.com/weavejester/lein-ring/blob/be43e45b8648f9fe2c758b1d27cae0a59eafa9d3/src/leiningen/ring/jar.clj#L30 (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?

joshkh18:09:56

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

joshkh18:09:04

the last example being the truthiness behind the if

joshkh18:09:42

@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)

joshkh18:09:06

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

Azzurite18:09:00

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

joshkh18:09:38

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.

seancorfield18:09:41

@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.

seancorfield18:09:58

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

seancorfield18:09:55

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

Azzurite19:09:42

that makes sense, thanks everyone

bringe20:09:04

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?

bringe20:09:22

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.

borkdude20:09:31

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

bringe20:09:05

ohhh, that makes sense. Thanks!

borkdude20:09:50

@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
hoopes22:09:21

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 - http://http-kit.org/600k-concurrent-connection-http-kit.html . 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.

Azzurite22:09:27

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

Azzurite22:09:40

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

hoopes22:09:30

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

hoopes22:09:48

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

Azzurite22:09:54

If you want to run web apps, yeah

Azzurite22:09:17

Depends on your environment

Azzurite22:09:33

It just serves your site on a port

hoopes22:09:35

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)

Azzurite22:09:47

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

hoopes22:09:11

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

Azzurite22:09:48

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

Azzurite22:09:02

It seems insane that that even seems to exist in python

hoopes22:09:58

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

Azzurite22:09:12

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.