Fork me on GitHub
#clojure
<
2017-06-02
>
noisesmith00:06:53

well 100 numbers is definitely more than 120 wide (or is it counting “items” rather than string length?)

micahasmith13:06:21

good morning! core.cached question:

(if (cache/has? C :c)
      (cache/hit C :c)
      (cache/miss C :c 42))
how is it possible with this code that :c will definitely survive in between /has? and /hit? would think they’d have to be wrapped together in some way (macro?) for that to happen

micahasmith13:06:26

or does /has? under the hood flag for holding until /hit

mpenet13:06:08

could be wrong, but isn't it immutable, thus safe (returns a new cache) ?

micahasmith13:06:48

(require '[clojure.core.cache :as cache])
	
(def C (cache/fifo-cache-factory {:a 1, :b 2}))
	
    (if (cache/has? C :c)
      (cache/hit C :c)
      (cache/miss C :c 42))

micahasmith13:06:06

C looks kinda atom-esque

mpenet13:06:15

it's not, it's immutable if I recall

mpenet13:06:22

personally I prefer to use caffeine for this kind of things

mpenet13:06:44

it has more knobs, but it's very java'esque

mpenet13:06:28

woa, I actually forgot I published this 😛

mpenet13:06:36

thought it was in our internal repo

mpenet13:06:33

the java api is not that bad actually (that lib only makes it edn-configurable and saves type hinting here and there)

weavejester14:06:06

@micahasmith The way core.cache is used in practice isn’t well documented IMO

weavejester14:06:52

Typically you have something like:

weavejester14:06:57

(defn with-cache [cache key value-fn]
  (-> cache
      (swap! #(cache/through value-fn % key)
      (cache/lookup key)))

weavejester14:06:26

through uses that has?/`hit`/`miss` logic

weavejester14:06:51

It’s just for updating the cache

weavejester14:06:21

If you put the cache in an atom, it can be updated using swap!, which conveniently returns the immutable cache as a value.

weavejester14:06:34

This return value can then be used to lookup the key.

dalekbaldwin14:06:44

is there a version of the EDN reader available as a standalone library, that I could read EDN files with namespaced maps in clojure 1.8?

captainlexington15:06:18

A standalone library instead of the clojure.edn namespace?

captainlexington15:06:20

I'm not sure I understand the second half of the sentence - what's wrong with using clojure.edn?

dalekbaldwin15:06:54

if I use clojure 1.8 in my project.clj, then I get the 1.8 version of clojure.edn, which doesn’t understand namespaced maps

dalekbaldwin15:06:45

I produced a bunch of data from another project using 1.9, and it’s full of namespaced maps

ghadi15:06:55

[org.clojure/tools.reader "1.0.0-RC1"]

dalekbaldwin15:06:25

is that an EDN reader, or a clojure code reader?

ghadi15:06:49

both actually

ghadi15:06:00

has variants IIRC

dalekbaldwin15:06:23

I’ll check it out, thanks

nadejde15:06:25

Hi guys! Clojure noob here so please be gentle:D I’m playing with Ring/Compojure-api to try and get some understanding how one would build an API in clojure. The question I have is this: I have a function in a db namespace called db/find-user. This function depends on external database (datomic in this instance if it matters). When consuming this function at the service/handler level (or in other places) what would be the most clojure way to deal with this? Should I pass the db/find-user function as argument into functions that need to consume it (end upwards on the stack) or do I just take the hit and use it as a “hidden” dependency? Example of what I mean:

(ns example.core
    (:require [example.db :as db])

;;1. hidden dependency way?
(defn vaild-user [credentials]
    (let [user (db/find-user credentials)]
        (do-more-with-user user)))
    
(defn function-that-uses-valid-user [credentials]
    (valid-user [credentials]))

;;2. passing dependency as argument
(defn valid-user-2 [find-user credentials]
    (let [user (find-user credentials)]
        (do-more-with-user user)))
;;this seems to have a disadvantage as I have to move db/find-user upp the stack
(defn function-that-uses-valid-user [credentials] ;;and this potentially needs find-user as an argument if it gets called upwards on the stack
    (valid-user-2 [db/find-user credentials]))
Sorry if it’s a stupid question 😞

nadejde15:06:07

Does it even matter?

seancorfield15:06:46

What we tend to do is have the system configuration in a Component and have middleware that adds that to the Ring request.

nadejde15:06:41

Ok. So you do move the dependency to the uppermost level on the stak and pass it down the levels.

seancorfield15:06:42

So handlers can get (:my-app/config req) and inside that there’s a :my-db which is a pooled datasource.

seancorfield15:06:32

The alternative would be packaging your “data tier” as a Component and passing that around (easier to mock perhaps for testing).

seancorfield15:06:18

But, yeah, pass everything in via the request and set it up in middleware would be my preferred approach. @weavejester you were about to suggest something? Would love to hear your recommendation as the creator of Ring.

weavejester15:06:42

I was typing something, but got distracted 🙂

robert-stuttaford15:06:59

@weavejester has a recent blog post which covers this with Duct i believe

weavejester15:06:23

@nadejde by db/find-user, do you mean the function itself or the database connection?

weavejester15:06:34

Or a closure wrapping find-user with the database connection?

nadejde15:06:17

db/find-user would enclose the database connection I guess

weavejester15:06:12

And by credentials you mean the user’s username and password?

weavejester15:06:20

So this is a user authentication?

nadejde15:06:54

yes. in this case it would be. It can be anything else. I just picked this as an example

weavejester16:06:38

In the basic case I’d write something like:

(defn user-endpoint [db]
  (GET "/user/:id" [id]
    (find-user db id)))

weavejester16:06:54

So I have a function that returns a handler/route

weavejester16:06:19

By using a closure we can pass the db connection in once, and also perform any setup we need.

weavejester16:06:33

I’ve also taken to writing protocols around my I/O boundaries

weavejester16:06:33

(defprotocol Users
  (find-user [db id]))

(extend-protocol Users
  foo.component.Database
  (find-user [{:keys [spec]} id] ...))

weavejester16:06:16

This loosens the coupling between the handler and the database. When testing I can replace the real database with a stubbed or mocked one.

weavejester16:06:45

It’s also useful when communicating with external APIs. During development you can subtitute in a local API that mocks out a cloud service.

weavejester16:06:00

This approach works well with Component or Integrant.

weavejester16:06:10

@robert-stuttaford mentioned Duct, which is currently in alpha, but I’ll release a beta today. That’s a more opinionated framework built on top of Integrant, but follows the same basic ideas of passing dependencies as arguments, and using closures.

nadejde16:06:34

Thank you very much for you help and suggestions! I will now go and research about what you guys said for a couple of weeks:) I’ve not used Component or Integrant before. But I hope I can figure it out! Thank you again!

nadejde16:06:54

I will also have a look at Duct 🙂

weavejester16:06:21

@nadejde The information on the Duct page is currently for the soon-to-be-outdated stable version. You might want to look at https://www.booleanknot.com/blog/2017/05/09/advancing-duct.html and https://www.booleanknot.com/blog/2017/05/29/building-web-services-with-duct.html if you’re interested.

nadejde16:06:56

will do this @weavejester thank you again

nadejde16:06:57

One more if you might please? For learning my way into this what would you recommend? Start low level with Ring and try to understand how to use all the different pieces together or through something like Duct and work my way down?

weavejester16:06:22

@nadejde I’m a fan of working my way from the bottom up if understanding is your goal.

weavejester16:06:36

Sometimes that’s not the most expedient way to get started

weavejester16:06:52

But it does lead to the greatest understanding

weavejester16:06:22

On the other hand, if you’re not doing something practical, it can be boring, and when things are interesting people learn faster.

nadejde16:06:12

Thank you. Will try and see how it goes with the buttom up. When I get bored look into a framework:) cheers!

seancorfield16:06:37

@weavejester Thanks. I hadn’t thought of functions-that-return-routes — because we have a lot of routes that would need this, but it’s an interesting approach for small apps.

weavejester16:06:55

@seancorfield It works for larger apps too, but it tends to require something like Component or Integrant to manage the dependencies.

seancorfield16:06:51

We have a lot of dependencies (and we’re using Component) and a lot of routes, so having the middleware as the closure-over-system and injecting it into the Ring request seems simpler than having a function-per-route?

seancorfield16:06:55

My colleague decided to use Bidi instead of Compojure in the app he’s working on and that seems to decouple handlers more completely but I haven’t had a chance to dig into that yet.

mping17:06:38

Hi there, anyone using deferredor aleph?

gsnewmark17:06:38

@mping check #aleph channel We're using both Manifold (deferred) and Aleph

joelsanchez18:06:08

@mping Built a realtime chat with aleph the other day

bj21:06:45

Meant to post in beginners, sorry

lvh22:06:32

I’m trying to remember the name of a clojure debugging tool that would basically print intermediate values in an expression; ISTR it was even in the stdlib, but I can’t find it anymore

lvh22:06:56

I have a function that has stuff like (not= some-expr some-other-expr) and it just tells me “true” which is useful but I’d love to know what the exprs were 🙂

lvh22:06:12

I just realized I probably want the word “instrumentation”

lvh22:06:06

yay, thanks!

lvh22:06:16

I don’t know if that’s what I remembered but it’s probably just as good 🙂

bfabry22:06:32

another possibility would be sayid, but I've never used it

john22:06:46

@joelsanchez source code or it didn't happen...

lvh22:06:06

I kinda want taoensso’s spy I guess, but I don’t want it to go to stdout; I want it as data

bfabry22:06:42

ohhhh. hmm. I'm not sure

joelsanchez22:06:41

@john Of course! Making a gist

joelsanchez22:06:01

Don't expect it to be perfect or full of features, it basically ensures that the message gets read by the target

joelsanchez22:06:17

Holds the messages until they are read

joelsanchez22:06:52

I made this to implement chat for a cordova app

joelsanchez22:06:21

It also communicates with PHP through zeromq, in another namespace, but who cares

joelsanchez22:06:43

Honestly most of the code you see is copied from aleph's documentation

john22:06:19

Yeah, I think I settled on aleph for the last chat system I worked on too.

john22:06:40

I tried so many though 🙂

joelsanchez23:06:49

I was considering several JS options (socketcluster, deepstream, plain old socket.io...), using ejabberd, learning Elixir like a real man, or doing it with Clojure

joelsanchez23:06:52

You know what I picked

qqq23:06:51

I'm writing a DSL for writing C code in Clojure. Long story. What's a good way to represent array access and dereference in Clojure? i.e. a[20] and *b

bfabry23:06:00

@qqq use the clojure array functions?

noisesmith23:06:30

use deref (@) to replace *

noisesmith23:06:38

you can extend dereffable

qqq23:06:03

(aset a 20 3) seems uglier than a[20]=3

qqq23:06:11

but also perfectly reasonable

bfabry23:06:24

it depends what your intentions with the dsl are I guess

qqq23:06:33

writing GPGPU code

bfabry23:06:27

yeah sorry I mean what you want the dsl to be like. like writing clojure that becomes C or like writing C

qqq23:06:13

oh, I want to write data that becoems C

qqq23:06:42

so something like

[:while [:x :< 20]
  [:x ;++]]

qqq23:06:49

hmm, maybe I'm just going to prepend a : to everything

bfabry23:06:15

wouldn't it be easier to use symbol sexpr data/

bfabry23:06:37

'(while (x < 20)
  (x ++))

hiredman23:06:49

or make it out of maps instead, with functions as short hand constructors

hiredman23:06:19

(defn while [condition body] {:op :while :condition condition :body body})

bfabry23:06:33

imo the parsing will be a lot easier if you just stick with good old prefix notation