Fork me on GitHub
#clojure
<
2016-08-02
>
kaosko00:08:23

(extend-protocol ...) seems to be very type oriented. is there a way to transform, say a column holding binary data in a specific table to something else (similar to @javax.persistence.Convert for the JPA folks) or do I have realize the results first and then transform?

seancorfield01:08:49

@kaosko: The java.jdbc uses of extend-protocol are intended for transforms at the type level, correct. To just "fix" a specific column, use :row-fn and provide a function that knows how to manipulate the row — (fn [row] (assoc row :converted-col (expand-data (:binary-col row))))

seancorfield01:08:02

(I assume you’re working with clojure.java.jdbc?)

kaosko01:08:38

yeah, java.jdbc. ah perfect, thanks @seancorfield

seancorfield05:08:02

@cpuntodanielcc: You're asking if you can build a Clojure app / library and release it under a different license than EPL? The answer is "yes".

seancorfield05:08:38

You can't re-license the Clojure code itself.

seancorfield06:08:20

(but if you're producing software you expect others to use, be aware that you might be making their lives more complicated by having to deal with two licenses instead of just one)

tjg10:08:06

When using namespaced keywords, is a good practice to define a namespace whose only purpose is to contain them? (Which you then require under an alias, to keep keywords short?)

tjg10:08:31

(If so, is there a convention for that namespace's name?)

levitanong10:08:26

By “defining a namespace”, do you mean like (ns a-namespace)?

levitanong10:08:59

If that is the case, then AFAIK the “namespace” in namespaced keywords are not the same, and are arbitrarily defined.

levitanong10:08:06

in other words, you don’t have to (ns).

tjg10:08:28

Ah, of course, duh, thanks.

levitanong10:08:50

No problem 🙂 It’s a namespace collision, so it’s an understandable confusion.

tjg10:08:46

But I guess then there's no way to refer to it with an alias if I don't define it with ns?

tjg10:08:48

For instance, if I (require '[clojure.string :as str]), ::str/foo is a handy shortcut for :clojure.string/foo)

mpenet10:08:07

you can just use create-ns

mpenet10:08:18

and alias for "shortcuts"

mpenet10:08:24

I do this often for namespaced keywords, so much that I ended up using a 2 line function that does both (ns-as 'foo.bar.baz 'baz) (prn ::baz/bar) => :foo.bar.baz/bar (see for more here: https://github.com/mpenet/ring-spec/blob/master/src/clj/qbits/ring_spec.clj)

tjg10:08:33

@mpenet: Ah perfect, thanks!

ricardo11:08:29

If anyone from JUXT hangs around here… the two Swagger-related links at https://yada.juxt.pro/hello.html are returning 500.

Yehonathan Sharvit11:08:43

A question related to clojure.pprint: Is there a way to pretty print a string? Let’s say I have a string that contains an expression and I want to pretty print it. My problem is is that clojure.pprint/pprint receives an object. I tried to to (pprint (read-string s)). But there are some weird cases (pprint (read-string “a\n123”)); returns “a”. Any idea?

ricardo11:08:54

Although looking at the footer, that might be out of date. I expect the latest is https://juxt.pro/yada/manual/index.html

mpenet11:08:43

@vlebel: just wrap the pprint call in with-out-str

mpenet11:08:08

(with-out-str (clojure.pprint/pprint ...))

Yehonathan Sharvit11:08:27

@mpenet: it doesn’t work. Look at this:

my.user=> (with-out-str (pprint (zipmap (range 14) (range 14))))
"{0 0,\n 7 7,\n 1 1,\n 4 4,\n 13 13,\n 6 6,\n 3 3,\n 12 12,\n 2 2,\n 11 11,\n 9 9,\n 5 5,\n 10 10,\n 8 8}\n"
my.user=> (with-out-str (pprint (str (zipmap (range 14) (range 14)))))
"\"{0 0, 7 7, 1 1, 4 4, 13 13, 6 6, 3 3, 12 12, 2 2, 11 11, 9 9, 5 5, 10 10, 8 8}\"\n"

Yehonathan Sharvit11:08:01

When pprint receives a string, it returns it as is, without doing any pretty formatting

mpenet11:08:45

it did format it on the first call

mpenet11:08:58

see all the \n after ","

Yehonathan Sharvit11:08:42

Yeah, because in the first call, I’m passing an object. While in the second call I’m passing a string.

mpenet11:08:22

(pprint (str ...)) will not do any formatting

mpenet11:08:42

if you want to have it pprinted you need to read it first

mpenet11:08:50

(as long as it's valid edn/clojure)

Yehonathan Sharvit11:08:13

I know. But I’m looking for a generic way to do it. And read-string reads only the first line. So (read-string "a\n123”) returns “a"

Yehonathan Sharvit11:08:41

This is the whole point of my question: how to pretty print a string that contains an expression?

mpenet11:08:23

you can just wrap the expression in a list, or you can use the reader directly

mpenet11:08:36

(str "[" exp "}") etc

mpenet11:08:09

ex: (with-out-str (pprint (read-string (str "(" (zipmap (range 14) (range 14)) ")"))))

Yehonathan Sharvit11:08:55

And then removing the first and the last character from the result. right?

mpenet11:08:03

yes for instance

Yehonathan Sharvit11:08:17

what do u mean by "you can use the reader directly”?

mpenet11:08:06

read the code sexp by sexp and apply pprint every exp, but dont bother, unless you're dealing with large files

Yehonathan Sharvit11:08:32

is there a function in the reader that can read sexp by sexp?

Yehonathan Sharvit11:08:40

or do I have to write my own?

mpenet11:08:21

read-string will do that

mpenet11:08:45

it reads only 1 sexp, hence the need for the (str ...) wrapping earlier

mpenet11:08:17

there's read if you want to work with streams, check the doc of c.c/read or it's equivalent in the edn namespace

ricardo12:08:19

Since there are yada fans in here… The docs at https://juxt.pro/yada/manual/intro.html state that you can add yada to Immutant. yada requires aleph/http, though. Is aleph the only supported server?

ricardo12:08:10

The yada project itself has a reference to clj-http on the dev dependencies, “to compare with aleph”, but it isn’t used. Also the “introducing yada” post from a couple of months ago (https://juxt.pro/blog/posts/yada-1.html) states only Netty is supported. Conflicting docs. 🙂

rickmoynihan12:08:02

I seem to remember @malcolmsparks mentioning it currently only worked with aleph... but I could be wrong

malcolmsparks12:08:25

It's aleph only, I have some undertow integration on a branch, hence Immutant support wpn't be far off

malcolmsparks13:08:07

There's a dedicated #C0702A7SB channel fwiw

schmir13:08:02

halgari says one should use aleph, cause it uses potemkin (https://www.reddit.com/r/Clojure/comments/4uvcp4/just_got_my_first_clojure_job_any_tips_for/d5tmf80)..I don't use aleph but use potemkin with great success. don't know how I should feel about that.

dominicm13:08:47

@schmir: I think he said you shouldn't use aleph

schmir13:08:54

dominicm: right, s/should/shouldn't/

dominicm13:08:54

I'm not sure the reasoning was entirely solid either. Potemkin is a few workarounds. But it's far from the devil.

dm313:08:07

Potemkin is just a library, not sure how it managed to aggravate the Reddit commenter that much...

dm313:08:32

to even stop using Aleph because it depends on potemkin

dominicm13:08:15

You are unlikely to see the effects of Potemkin whilst using Aleph, except for one thing: import-vars.

mpenet13:08:48

in the same vein there's the "don't use java wrappers just use interop.", depends on the wrapper/task imho

dominicm13:08:25

Sometimes it's nice to have had someone flesh out the java interaction for you, come up with some ideas about handling the state.

mpenet13:08:53

imagine having to deal with jackson manually to parse json -_- or deal with a mutability mess with most of db drivers out there

dm313:08:59

I guess usually it's because of interaction with poorly written wrappers which do not add anything useful (which in reality is probably the most of them)

dm313:08:15

but then there are many good ones

mpenet13:08:57

yup, no absolutes, "it depends"

dominicm13:08:44

> Use Kinesis + Kafka when possible. Off-load your work. Write re-playable code. (CQRSish) I found this suggestion interesting. Especially as I am currently exploring CQRS/ES as a design pattern. Is it a pattern that's prevailent in Clojure programs, that I haven't seen yet?

dm313:08:30

it's a bit confused, I'd say

dm313:08:53

1) use queues to offload the work (if you need to)

dm313:08:23

2) event sourcing helps (in certain cases), however there is a significant cost

dm313:08:06

3) CQRS helps both in the small and in the large (architecture), also not without cost

dm313:08:44

4) kinesis + kafka is just a technology, use at your own peril

dm313:08:34

not sure what's replayable code. Did he mean "side effect free + history available"?

dominicm13:08:44

@dm3: Sounds like you have some experience in the costs of CQRS/ES. Is there anything you could share to dig deeper? I only really see people talking about the benefits.

dominicm13:08:24

Replayable code is common in ES systems. You can take the events list, and "replay" them, through the system, to build up the same postgres database state.

dominicm13:08:42

It's quite an interesting idea. It makes blue/green deployments easy for example.

dm313:08:44

yeah, that's a projection

dm313:08:06

never saw the "replayable code" name

dominicm13:08:37

Hmm, it's the name I've seen for it. Naming is the hardest problem.

dm313:08:15

I don't have any great tips for CQRS/ES systems, except that it incurs a significant cost

dm313:08:31

so you really need to make sure the benefits are there

dm313:08:43

e.g. if your domain looks CRUDish - don't use it

dm313:08:50

but there are lots of complexity layers behind a CQRS/ES implementation

gnejs13:08:50

(one advice from Greg Young is to only implement ES for the most important/crucial parts of your domain-model - not for the entire application)

dm313:08:59

yes, that too

gnejs13:08:08

just because of the cost dm3 mentioned 🙂

dm313:08:25

so you can start with a simple implementation

dm313:08:34

which is ~200 lines of clojure code 🙂

gnejs13:08:42

and ES requires a well though-out domain-model (a la DDD).

mpenet13:08:52

mostly useful in exactly once delivery scenarios and/or where auditing is crutial

dominicm13:08:52

@gnejs: I found that advice strange. As I think there's a lot of value in reinterpreting the entire history of your application to do analytical data later. But maybe that's just me.

gnejs13:08:56

events should only apply to isolated domain aggregates, or all hell breaks lose 🙂

dominicm13:08:45

I think the pre-planning required for DDD is well encouraged within the Clojure community. So that may be less of a problem (although, naming is always hard!)

gnejs13:08:47

@dominicm: I think there’s an important distinction between application and domain model there.

dm313:08:06

there is a lot of uses for the events

dm313:08:13

it doesn't mean you have to event source

dominicm13:08:48

@gnejs: Hmm, I'm struggling to understand application model here. Could you point me at some information about the differentiation between the two things?

gnejs13:08:40

The DDD-book is a good reference… and youtube videos by Greg Young. Also I think Vaugh Vernon have written stuff about it. IMO the domain-model is something that is central to the business itself and not scoped to a particular usage == application.

gnejs13:08:49

It’s all about layers 🙂 Although with all the microservice hype the traditional “enterprisey layering” have gone out of style a but I guess 🙂

dominicm13:08:43

@gnejs: I'll have to get the book. And look into Vaugh, as I've only seen Greg realy. Could you give an example of model which might be considered application-level?

gnejs13:08:44

actually - I think Martin Fowlers book http://martinfowler.com/eaaCatalog/ describes the difference a bit.

dominicm13:08:57

Interesting.

dominicm13:08:25

I'll admit that I find microservices less useful. I'm still discovering other old ideas! 😛

joost-diepenmaat13:08:42

since people are talking about event sourcing, I want to mention I’m working on some refactoring/restructuring of the rill event sourcing tooling @ https://github.com/rill-event-sourcing/wheel

gnejs13:08:57

I guess there might be more layers than those two.. but IMO the application model might be about how users are defined, authorization, page-navigation (and to some extent: persistence, caching etc - but a better word might be ‘infrastructure’). While domain model would be about the core business concepts (shipping, trading, salary concepts etc.).

gnejs13:08:39

@joost-diepenmaat: looks interesting… adding to Pocket for later 🙂

dominicm13:08:50

@joost-diepenmaat: I'll defin- ^^ that's what I was saying

joost-diepenmaat13:08:04

If you have any questions or remarks don’t hesitate to let me know. We are experimenting with it at the moment trying to get the “feel” of the library correct so that implementations using it read “nice”.

dominicm13:08:07

@gnejs: For the most part, that example about the split is exactly how I was thinking of modelling it. In that context, Greg's advice makes a LOT more sense to me.

joost-diepenmaat13:08:33

oh and all of this is aimed at the write side of CQRS. it defines nothing about the read side (the assumption is you’re doing that on your own based on some process that’s listening to all events)

dominicm13:08:28

I did want to experiment with storing other events (http requests for example) too though, but purely for analytical information. So that could be considered part of the domain, albeit in a different sense. I was struggling to decide where the boundaries were.

gnejs13:08:24

imo, one of the cool things about ES is that the event-store-side only really need to contain checks for invariants. The actual “data model” can be darn thin. If an update contains 20 fields it’s only necessary to persist those fields that are relevant for maintaining the integrity of the model. All 20 fields is propagated to the read-side though.

gnejs13:08:37

@dominicm: isn’t that something that ppl are using Kafka http://et.al for? I.e. it doesn’t have to be modelled as an "Event Sourced Domain Aggregate”.

dominicm13:08:42

@gnejs: I don't think Kafka is suited to persistent storage of those events. And I didn't really want to do anything with the information straight away, just create a big pile events to do something with some day.

gnejs13:08:04

@dominicm: true - I don’t think Kafka is a long-term storage alternative either. But it can be used as an ‘ordered channel’ to pipe the events to a more suitable store?

dominicm13:08:14

@gnejs: Ah, I think I misunderstood your question. Yes then. My comment was more about the blur of boundaries when you start making your application part of your domain (as I guess you do in analytics)

gnejs14:08:18

it’s a different domain perhaps.. the best chapter in the DDD book is the one about bounded contexts 🙂

gnejs14:08:32

http://martinfowler.com/bliki/BoundedContext.html — the ‘analytics’ domain could be squeezed in there as an adjecent ‘bounded context’ perhaps?

dominicm14:08:43

I'm gonna have to get this book! I've largely ignored DDD so far. That's clearly a mistake.

gnejs14:08:04

ah.. sorry… that’s a local link… hang on 🙂

daveliepmann14:08:20

I'm destructuring a map argument to a function. Is there a way to error out if a key is passed that is not present in :keys? E.g. I'd like to throw an exception in the following case, because otherwise :c is silently ignored: (let [{:keys [a b]} {:a "a" :b "b" :c "c"}] [a b])

gnejs14:08:11

(there - updated the orig message)

gnejs14:08:28

(oh dear, that’s an ugly link… )

dominicm14:08:42

@gnejs: There's an #C0904S2QJ channel, perhaps we should continue there?

gnejs14:08:35

@dominicm: gah - would be fun, but I need to leave work in a couple of minutes.. will join it though!

dominicm14:08:48

@gnejs: Thanks for the pdf!

joost-diepenmaat14:08:39

@gnejs: yeah thanks that looks interesting

dpsutton15:08:03

does anyone know how to get a parse a clojure.instant into a clj-time object? basically java.util.Date -> org.joda.time.time.DateTime

dpsutton15:08:39

the string representation of the inst isn't one of the formatters listed for clj-time (f/show-formatters) so the two don't seem to have an easy interoperability

codonnell15:08:07

@dpsutton: check out clj-time.coerce/from-date

dpsutton15:08:21

ah. much thanks

mokr15:08:47

Does anyone know if some kind of sort order can be assumed for: (file-seq (http://clojure.java.io/file "/some/path”))

mpenet16:08:26

mokr: nope, it's not specified, so I guess it can even vary from platform to platform

mokr16:08:16

Thanks, that was what I expected, but wanted to ask before I started to implement sorting.

bodie16:08:15

Hello hello’s 🙂

akiroz16:08:20

hey there~

kaosko17:08:27

hello there.. writing a compojure api, how I do describe a schema for a vector of vectors?

kaosko17:08:15

(defschema ... :coordinates [[Integer Integer]] results in "[java.lang.Integer java.lang.Integer] is not a valid sequence schema"

gfredericks17:08:36

[[Integer]] should work

gfredericks17:08:59

or if you mean a vector of pairs of integers, then [[(s/one :x Integer) (s/one :y Integer)]] or something like that

kaosko17:08:16

thanks, but [[Integer]] results in "errors": "(not (map? \"\"))" (obviously I don't want a map)

gfredericks17:08:27

that sounds like it's related to something else

kaosko17:08:43

[[(s/one :x Integer) (s/one :y Integer)]] results in No implementation of method: :spec of protocol: #'schema.core/Schema found for class: clojure.lang.Keyword

gfredericks17:08:04

I probably have the args to s/one backwards for that one

kaosko17:08:51

hmm ok. I'll try again

kaosko17:08:34

switching the order I get the same "errors": "(not (map? \"\"))", so I suppose that works but the problem may be elsewhere, thanks

bodie19:08:33

how can I define a function that takes a function f and varags fns and returns a function of some arg val which first calls (f val) followed by each successive fn from fns? let’s just say I wanted to chain side effects after a call

bodie19:08:37

I’m a bad person etc etc

bodie19:08:53

I was trying to use juxt but I realize that’s wrong now (I think)

bodie19:08:58

(defn wrap
  [f g] (fn [arg] (do (f arg) (g arg)))
  [f g & fs] ( ??? ))
I guess just loop?

bodie19:08:36

I was kind of hoping to somehow use threading or wrap each fn in a subsequent closure but I guess that would accomplish the same thing

dg19:08:56

If you have a list of functions '(f1 f2 f3) then (apply comp fnlist) to compose them

bodie19:08:10

Nice, just what I was looking for. Thanks @dg

bodie20:08:32

@dg: so if I have [f g & fns] I’d want to return (apply comp (conj (conj fns g) f)) … ?

dg20:08:33

To discard return values (ie a list of side effects), (doseq [f fns] (f arg))

bodie20:08:58

somehow I feel I’m missing the spirit of this 😉

dg20:08:16

To compose the values (feeding the return of each into the next), then (apply comp f g fs)

bodie20:08:52

ah, did not realize apply would not make that into [f g [f1 f2 f3 ...]]

dg20:08:17

yeah, apply should flatten it out and return a function, which you'd then execute with arg

bodie20:08:45

Awesome, thanks

bodie20:08:27

Oh I see: “the argument list formed by prepending intervening arguments to args"

fabrao20:08:04

Hello all, a silly question, is there any way to use reduce not lazy in this

(reduce #(assoc %1 (keyword (str %2)) 0) {} (take 31 (iterate inc 1))) 
?

fabrao20:08:40

The result is

{:14 0, :27 0, :31 0, :18 0, :12 0, :11 0, :24 0, :10 0, :21 0, :23 0, :13 0, :30 0, :4 0, :26 0, :16 0, :7 0, :1 0, :8 0, :22 0, :25 0, :9 0, :20 0, :17 0, :28 0, :19 0, :2 0, :5 0, :15 0, :3 0, :6 0, :29 0} 
, not ordered

gfredericks20:08:52

@fabrao: reduce is already not lazy -- what's your problem with that result?

fabrao20:08:02

well, why it´s not ordered if

(take 31 (iterate inc 1))
is in sequence (1 2 3 ...31)

gfredericks20:08:13

maps aren't ordered

fabrao20:08:54

so, sorting will be good 🙂 ?

gfredericks20:08:09

depends on what you want; it won't be a map after sorting

gfredericks20:08:27

and if you want it to be the same order as it was when it went in, then why not use map instead of reduce?

fabrao20:08:12

because the result is like this ({:1 0} {:2 0} ... {:31 0}) not {:1 0, :2 0 ... ;31 0}

fabrao20:08:45

I think I´m newbe to convert it to map, sorry

gfredericks20:08:00

the question is how you're going to use the result

gfredericks20:08:13

do you really need it to be ordered AND to be a map, or do you just need one of those things?

jjfine20:08:37

looks like @fabrao wants a list of maps?

jjfine21:08:47

in that case (map #(hash-map (keyword (str %)) 0) (range 31)) ?

jjfine21:08:51

but still not sure that's what's being asked

fabrao21:08:25

(map #(hash-map (keyword (str %)) 0) (range 31)) -> ({:0 0} {:1 0} ...) not {:0 0, :1 0 ...}

ghosss22:08:42

@fabrao: if you really need a sorted map with integer keywords... you could do this:

(apply sorted-map-by
       #(< (Integer/parseInt (name %)) (Integer/parseInt (name %2)))
       (interleave (map (comp keyword str) (range 32)) (repeat 0)))
but why do you want the map to be sorted?

fabrao22:08:47

because this is a sequence of days for report

gfredericks22:08:14

are you going to look up keys in the map? or just iterate over the entries?

fabrao22:08:18

well, It´s an array-map of sequence of days

ghosss22:08:34

at 31 entries, maybe you might as well just use a vector of length 31? forget using a map

gfredericks22:08:39

are you going to look up keys?

fabrao22:08:46

so I´ll iterate after to fill the tickets count by day

fabrao22:08:32

@ghosss: I´ll try it

spei22:08:38

(reduce #(assoc %1 (keyword (str %2)) 0) (sorted-map) (range 31))

gfredericks22:08:46

you also might consider not using keyword keys

gfredericks22:08:52

if you change them to integers you could just use a vector

fabrao22:08:47

yes, it´s better idea

fabrao22:08:45

but the I have to pass the reference of day to a chart, that´s because I need keyword

gfredericks22:08:09

you could convert it just before passing it

chbm22:08:45

rest servers are still based on ring or are cool kids doing something else now ?

shaun-mahood22:08:39

@chbm: The ones I'm aware of are either based on ring or pedestal. Any specific things you are wondering about?

chbm22:08:09

i used ring for basic ws stuff a couple of years ago but i remember reading about new frameworks, was wondering what was the preferred middleware - router stack for webservices now

akiva22:08:48

Some of the popular frameworks—such as Luminus—wrap around ring.

danielcompton23:08:01

Also Yada is pretty new, but has some neat ideas

akiva23:08:52

I have Yada in my ‘look at this’ folder and… well, I’ve yet to look at ‘look at this’.