Fork me on GitHub
#clojure
<
2016-11-25
>
seancorfield07:11:51

@oliv assuming you're talking about a Ring application, the recommended solution would be to add middleware that adds your global configuration to the Ring request. That decouples the dependency from the controller and from the service functions you call. It makes the entire call chain both more reusable and easier to test. And it doesn't change the signature of the controller either.

pythonruby08:11:45

Hi, what's the performance of realizing an element in infinite sequence with many lazy functions stacked upon it. Take generating prime numbers for example, whenever a prime number is found, a remove function is added to the lazy remaining seq, e.g.

remove (fn[x] (= 0 (rem x primeNum))) remaining))
. To my understanding, when an element is realized, lot's of remove functions need to be called, e.g. for 10, remove function for 2, 3, 5 and 7 needed to be called. Do I understand it correctly?

slipset08:11:27

@oliv: another trick you can use is something like the following:

slipset08:11:30

(defn save-explicit [file text]
  (spit file text))

(def save (partial save-explicit “foo.txt”))

slipset08:11:38

I’m, ahem, partial, to using to using partial over anon-fns where the first param stays the same.

pupeno09:11:40

What’s the best way to have Clojure web servers communicate with each other?

mccraigmccraig09:11:19

@pupeno gnatsd has been working well for me, with clj-nats-async

pupeno09:11:44

@mccraigmccraig do you host a gnatsd server yourself?

mccraigmccraig09:11:00

@pupeno yeah, i have a gnatsd cluster deployed alongside the rest of my app components

pupeno09:11:23

I’m not sure how well that will work on Heroku.

mccraigmccraig09:11:07

ah, you might need to find a heroku addon then

pupeno09:11:09

Maybe I should use redis pubsub

mccraigmccraig09:11:32

i've never used it, but i heard redis pubsub was pretty good, probably given the usual redis caveats

pupeno09:11:29

@mccraigmccraig what redis caveats? I haven’t use redis yet.

mccraigmccraig09:11:23

problems are related to HA configurations iirc, so you are fine with a single-sever setup

pupeno10:11:55

There’s also PostgreSQL listen/notify

mccraigmccraig10:11:29

oh, yeah, that would def make sense if you are already using pg

pupeno10:11:53

Except that the PG JDBC driver doesn’t seem to support it. sigh

spacepluk10:11:13

any ferret users around?

niwinz10:11:08

@pupeno yes it supports it

pupeno10:11:32

niwinz oh, does it?

niwinz10:11:08

there are the pgjdbc-ng driver that has better support for it

colin.yates11:11:06

hi all - quick Q - I am sure there is a more idiomatic approach than (map vector [1 2 3] [2 3 4]) to give [[1 2] [2 3] [3 4]] but I can’t remember it - any ideas?

kauko11:11:12

(conj [] [1 2 3] [4 5 6])?

kauko11:11:33

Honestly that looks pretty idiomatic to me!

miikka14:11:10

I always try to do (zip [1 2 3] [2 3 4]) just to find out that there's no zip in clojure.core 😛

miikka14:11:27

to achieve what (map vector [1 2 3] [2 3 4]) does, that is

miikka14:11:03

but that gives you a map

mpenet14:11:45

@pupeno we use redis here, happy with it so far (there are tradeoffs tho compared to the alternatives, ex wrt consistency). We have sort of "remote atoms" connected to redis, so we can "add-watch" etc etc, deref is local/cached, all updates are in the background.

mpenet14:11:21

If I'do it now I'd probably choose something more robust tho

pupeno15:11:17

@mpenet why watching atoms instead of pubsub?

mpenet15:11:01

it's pubsub, it's just has an atom like interface (it's a component you can deref and that has !! fns for all atom equivalent functions)

mpenet15:11:35

under the hood it's redis pub/sub for notifications of changes + normal keys for persisting stuff across restarts

pupeno15:11:36

I see. Interesting. I just need the pub sub though

mpenet15:11:17

if you use carmine for pub/sub on redis be aware it doesnt handle reconnections & failures

mpenet15:11:33

you'd have to code this stuff yourself

pupeno15:11:39

Oh, good to know.

mpenet15:11:25

lettuce (java lib) does

mpenet15:11:48

overall it looks like a nice/complete library

rickmoynihan16:11:19

@oliv: A very practical reason, rather than theoretical reason, why that code you pasted is bad, is that the save operation occurs when the namespace is read. If you take that code, and try and build an uberjar with it, you’ll see that the save operation actually occurs at compile time. Often these kind of side-effects can actually prevent the uberjar process from finishing too (e.g. if it fires off daeomon threads by maybe starting a web-server). If you want the code to execute when the script is loaded, just make it a -main function or call it from the outside explicitly

rickmoynihan16:11:52

also if that happened in a library, users of the library would have no control over when that side effect happened… it would complect that effect, with making the functions available to users.

colin.yates16:11:29

thanks @miikka and @robert-stuttaford (and yeah, a map is most definitely not what I want here ;-))

tdantas18:11:33

hey @seancorfield thx for your answer (https://clojurians.slack.com/archives/clojure/p1480059591016898) yeah, using ring, your are right ! let’s suppose my service function signup-user

1. verify if email/password are not blank
2. verify if email was already taken by someone else ( check agains database )
3. save the new user ( database )
4. send one message to the queue system ( signup.user ) with the step 3 persisted data
so, if I understood correctly, we are going to create middlewares to assoc with the request map the :database db-connection and the :queue queue-connection my service function signup-user will receive the request and fetch everything from there
(defn signup-user [ { database :database queue :queue } request] 
   ;; code here 
)
is that correct ? @seancorfield ( and all others who want to join and talk about it )

seancorfield18:11:08

Something like that, yes. I’d use namespaced keywords, to avoid possible conflicts, and probably add a single :my.app/config key with a configuration map.

seancorfield18:11:40

In our Ring apps, we have a Component (Stuart Sierra’s library) added to all Ring requests as middleware.

seancorfield18:11:08

And that Component contains all our DB connection pools, our “environment”, and so on.

tdantas18:11:55

that is cool ! and the service functions will receive the component already started and the request

tdantas18:11:03

and inside the service function you fetch what you want from the request and pass through the composed functions

seancorfield18:11:03

In general, we only pass what a function needs but that might be the entire application component or just part of it.

seancorfield18:11:50

(defn my-controller [{:keys [my.app/config] :as request] …)

seancorfield18:11:04

That’s how we prefer to do the destructuring.

tdantas18:11:45

much better than pass the request down in the service function

jgh20:11:32

Does anyone know if there's a way to have compojure/httpkit call a specific function in case of a 404? E.g. the route is not defined in defroutes, so call my function instead of responding with a default 404.

jgh20:11:42

nm found it -- (compojure.route/not-found my-404-function) in defroutes

adamkowalski20:11:16

Whats the best way to persist a clojure data structure to disk? Like if I just wish to make a simple log that I keep appending to the end of but I want to have high throughput what should I do?

adamkowalski20:11:44

Do you use something like spit, or do you use FileOutputStreams, or FileChannels? And what is the recommended way of serializing the data so it can be written.

Alex Miller (Clojure team)20:11:39

streams are byte-oriented, so generally you want to use something like a Java reader (character-oriented)

Alex Miller (Clojure team)20:11:54

and you can use pr-str to get a data structure as a string

adamkowalski21:11:49

Ok, and what about reading from a file

adamkowalski21:11:59

is there a way to read and write simultaniously?

adamkowalski21:11:13

ideally I could have something which only has to write, but always writes to the end of the log

adamkowalski21:11:58

then separately I wan’t to read from that same log, but I was hoping to have many readers and then can keep track of their own place in the log

adamkowalski21:11:16

maybe after each read you return the offset in the file that you are on so you can pick back up where you left off