Fork me on GitHub
#clojure
<
2015-12-04
>
pvinis00:12:40

jaredly: partition with the step arg is cool

pvinis00:12:45

also didnt know that

pvinis00:12:51

thanks! that works nicely

jaredly00:12:03

yeah, it comes in handy

jaredly00:12:06

pkobrien: yeah, makes sense

roelof07:12:33

I have a problem that I cannot solve

roelof07:12:47

I try to make a very simple accounting system

roelof07:12:08

Now I try to take care that when a account increased with a amount , another account is decreased with the same amount

roelof07:12:21

I thought I could do this with a map like this [ { :account cash withdraw 100} {:account bank desposit 100} } ]

roelof07:12:13

and use a dosync to update both accounts at once

roelof07:12:35

but now I wonder how can I descruct both maps in one time so the variable account1 will be cash here. amount1 will be 100. account2 will be bank and amount2 will also be 100

roelof07:12:13

at this moment there are only 2 accounts but later on the list could contains 2 to maybe 10 entries

andy.fingerhut07:12:28

@roelof: You can do lots of computation inside of a dosync, if you wish. Looping over 2 to 10 entries describing a desired transaction isn't a lot of computation.

andy.fingerhut07:12:59

@roelof: No need to destructure every transaction in the sequence in a single expression. Loop through them and destructure each one, one at a time.

dmitrig0107:12:24

you could also just put the whole system in a single atom

roelof07:12:53

@andy.fingerhut: so use a map for the looping

roelof07:12:18

how can I then check the best if all entries together will be zero

andy.fingerhut07:12:27

@roelof: What you called a 'map' above is a vector of maps. Loop through the vector and process each map one at a time.

roelof07:12:32

oke, but first I have to check if the whole vector amounts together will be zero

roelof07:12:50

zo I need a filter and a map for that I think

andy.fingerhut07:12:10

@roelof: You can check whether the transaction has 'total withdraws equals total deposits' before even starting the dosync, and avoid starting the dosync if that is not true.

roelof07:12:39

oke, I think I need a filter and some maps for it

roelof07:12:50

and maybe some variables holding some values

roelof07:12:24

enought to test and experiment with this

roelof07:12:35

so lot's of fun simple_smile

andy.fingerhut07:12:36

@roelof: If v is equal to the vector of maps you gave above, try out (filter #(contains? % 'withdraw) v) in the REPL

andy.fingerhut07:12:55

and similarly replacing 'withdraw with 'deposit

roelof08:12:03

@andy.fingerhut: I know that one and then I need to use I think sum to get the total of withdraw

roelof08:12:19

the same for deposit

roelof08:12:16

and the difference between those two must be zero

roelof08:12:56

I hope only that clojure not thinmy numbers are floats otherwise I will not work

roelof08:12:14

when the amounts are 11.50 for example

roelof08:12:42

oke, then the outcome will be 0.0

roelof08:12:57

@andy.fingerhut: thanks for the tips as I said enough to experiment with today and maybe tomorrow

roelof08:12:06

Hmm, I see this output : => ({:account #object[clojure.lang.Ref 0x627f264f {:status :ready, :val {:amount 0}}], :withdraw 100}) I miss the name of the ref

roelof08:12:18

How can I take care of this?

roelof08:12:22

I get the output of this function : (filter #(contains? % :withdraw) v))

jaen08:12:22

@roelof: you have to name your ref somehow, just like you have to name other values - (def something 12) or (let [something 12] ...) depending on what you want to achieve.

jaen08:12:42

If that's your global state then you probably want to def it

moizsj09:12:31

can someone spot whats wrong with this? (defn thrower-catcher [f] (try (f) (catch ArithmeticException a "div b z") (finallY (print "done"))))

moizsj09:12:10

pls ignore

crankyadmin09:12:35

Morning all, I have some pipe delimited files sitting in HDFS and I'd like to use Hadoop (ideally with Clojure) to load them into another system with via a http api. Any suggestions on the best approach?

roelof09:12:35

oke, so I can make a let for the find and one for the deref ?

jaen09:12:23

I'm not sure I understand the question, to be honest.

roelof09:12:27

@jaen: do said earlier to me that I can use a let statement so :account has a value not a reference

jaen09:12:17

ah what you mean is you want something like

jaen09:12:51

(def account1 (ref ...))
(def account2 (ref ...))

(dosync
  (let [current-state-of-account1 @account1
        current-state-of-account2 @account2
        new-value1 (some computation)
        new-value2 (some computation)]
  (reset! account1 new-value1)
  (reset! account2 new-value2))

jaen09:12:56

Or do you mean something else?

roelof09:12:07

oke, current state is the "old" value ?

roelof09:12:27

@jaen that is the next step

jaen09:12:34

current-state is the current value

jaen09:12:37

Generally

jaen09:12:06

@something means "get the current value of something", when something is reference type.

jaen09:12:25

So you just make a snapshot of how it looks at the moment you @ it.

roelof09:12:32

Im at the point that I have this [ {:account cash :withdraw 100 } {account :deposit 100} ]

roelof09:12:55

and I try to count all the items which has :withdraw in it

roelof09:12:17

so I can check if all the withdraws minus the deposits are zero

jaen09:12:01

I suggest not having account inside the map, because when you iterate over the transactions, if you deref accounts for each map it's value can change in the mean time.

jaen09:12:10

I think it would be better to structure your transactions like so

roelof09:12:36

so I thought that filter bring me all the withdraws and later all the deposit and I could use a map to make the total of the withdraws or deposit

jaen09:12:01

Yes, you could filter it out

jaen09:12:11

Or just do it in one step with reduce, like so

jaen10:12:37

(reduce (fn [balances {:keys [account withdraw deposit]}]
          (cond 
            withdraw (update balances account #(- (or % 0) withdraw))
            deposit  (update balances account #(+ (or % 0) deposit))))
        {} transactions)

jaen10:12:42

You will then end up with something like

jaen10:12:56

{account1 -100
 account2 100}

jaen10:12:03

And in a transaction you could then do

jaen10:12:14

(dosync
  (doseq [[account balance-change] balance-changes]    
    (swap! account (fn [account]
                     (let [new-balance (+ (:balance @account) balance-change)]
                       (if (< new-balance 0)
                         new-balance
                         (throw (Exception. "Insufficient funds"))))))))

roelof10:12:58

oke, and then i could use the outcome of the reduce to check if all the numbers added to each other will be zero

roelof10:12:30

if that is not zero then the user has made a error and nothing has to happens

roelof10:12:10

I will play and experiment with it

jaen10:12:18

Yeah, that's what I did in the last snippet

jaen10:12:25

At least if I understand what you want to do correctly

roelof10:12:46

oke, then I misunderstood the code at first sight

roelof10:12:24

one last question : are all the functions now pure ?

jaen10:12:32

@roelof: give me a second, I've checked the functions in repl just now and I see I made some mistakes, let me fix that first.

jaen10:12:26

(dosync
  (doseq [[account balance-change] (balance-changes transactions)]
    (alter account (fn [account]
                     (let [new-balance (+ (:balance account) balance-change)]
                       (if (>= new-balance 0)
                         (assoc account :balance new-balance)
                         (throw (Exception. "Insufficient funds"))))))))

jaen10:12:37

This is now correct

jaen10:12:02

I use mostly atoms so I forgot refs use alter not swap!

jaen10:12:13

(and had the logic subtly wrong)

roelof10:12:35

oke, but if atoms are easier, I can rewrite it to use atoms

jaen10:12:49

Nah, refs are appropriate here

roelof10:12:54

for me this is at this moment learning

jaen10:12:05

You need to coordinate different things in a transaction

jaen10:12:10

Only refs can do that.

roelof10:12:19

and hopefully learn and experiment enough to make a real project later

roelof10:12:44

Do I have to rewrite my calling vector with this code

roelof10:12:04

this code I will need later in that project

jaen10:12:22

If you wanted to change into atoms all accounts would have to be in one map, like so (atom {:account1 {:balance 100} :account2 {:balance 100}}). I think that would be more complicated for you right now, with having to use update-in and whatnot. Refs are probably simpler.

jaen10:12:38

I don't know what a "calling vector" is, sorry.

roelof10:12:53

I mean this with it [ { :account cash :deposit 100} { :account bank :withdraw 100}] with the calling vector

jaen10:12:51

Here, this is complete, working code I just tested in repl:

(def account1 (ref {:balance 100}))
(def account2 (ref {:balance 100}))

(defn balance-changes [transactions]
  (reduce (fn [balances {:keys [account withdraw deposit]}]
            (cond 
              withdraw (update balances account #(- (or % 0) withdraw))
              deposit  (update balances account #(+ (or % 0) deposit))))
          {} transactions))

(defn run-transactions! [transactions]
  (dosync
    (doseq [[account balance-change] (balance-changes transactions)]
      (alter account (fn [account]
                       (let [new-balance (+ (:balance account) balance-change)]
                         (if (>= new-balance 0)
                           (assoc account :balance new-balance)
                           (throw (Exception. "Insufficient funds")))))))))

jaen10:12:27

And then you can just call it like so (run-transactions! [{:account account1 :withdraw 100} {:account account2 :deposit 100}])

jaen10:12:32

And it should work properly.

roelof10:12:17

oke, thanks

roelof10:12:20

@jaen: I see this as output : CompilerException java.lang.Exception: Insufficint funds

roelof10:12:34

with looks no good to me

jaen10:12:22

I dunno, that looks good to me

jaen10:12:28

It just means you have insufficient funds

jaen10:12:29

Check it

jaen10:12:33

@account1

jaen10:12:36

what does it say.

roelof10:12:37

Found it. I think a old value was around. When I send first the def for both refs everything works well

jaen10:12:42

That happens ; d

jaen10:12:51

Now when you try to run-transactions! again

jaen10:12:55

You should get the exception again

jaen10:12:00

Which means it's working as it should

jaen10:12:03

Not letting you go under 0

roelof10:12:27

but I found another bug. When I do this one '(run-transactions! [{:account account1 :withdraw 100} {:account account2 :deposit 80}])

roelof10:12:53

it schould also fail because 100 is not equal to 80

roelof10:12:23

that is what I meant with all the withdraws minus all the deposit need to be zero

roelof10:12:37

I will look myself how to solve this one

jaen10:12:32

Yeah, you'd have to modify the code then

jaen10:12:39

But I think a better solution

jaen10:12:43

Is not to change this code

jaen10:12:46

But write functions

jaen10:12:52

That create proper deposits for the user

jaen10:12:56

And make sure that is correct there

jaen10:12:58

For example

jaen10:12:08

(make-transfer-transaction [from to value]) should return [{:account from :withdraw value} {:account to :deposit value}]

jaen10:12:17

That way you can make sure it is always correct

jaen10:12:36

And don't have to complicate balance-changes or run-transactions! too much

roelof10:12:26

Thanks, I will look at that

jaen10:12:14

This should be a fairly simple, two line function and would solve your problem

joelkuiper12:12:26

has anyone ever tried compojure-api/swagger with http-kit async channels?

joelkuiper12:12:41

The coercion mechanism doesn’t like it for obvious reasons, but not sure how to turn it off 😛

joelkuiper13:12:42

it attempt to coerce the channel to a json object, which obviously fails

juhoteperi13:12:03

@joelkuiper: Compojure-api default serializable? implementation should only serialize the response body if your endpoint has :return metadata or the body is a collection

juhoteperi13:12:31

So if you don't set :return metadata, I think channel as response should work

joelkuiper13:12:03

hmm doesn’t seem to be the case this is what I have now

(context*
   "/api" []

   (POST* "/annotateDocuments" req
          :components [matcher]
          :coercion (constantly nil)
          :middlewares [wrap-multipart-params]
          :swagger {:operationId "annotateDocuments"
                    :description "Provided a list of PDF files, will run the list of matched concepts and their annotations."}
          ;;:return dm/AnnotateResponse
          (process-documents req matcher))
….

joelkuiper13:12:53

where process documents returns the channel from http-kit (these are long running tasks, so don’t want to hog the request thread)

joelkuiper13:12:34

but gives

com.fasterxml.jackson.core.JsonGenerationException: Cannot JSON encode object of class: class org.httpkit.server.AsyncChannel: /0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:57095
    originalMessage: "Cannot JSON encode object of class: class org.httpkit.server.AsyncChannel: /0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:57095"

juhoteperi13:12:44

@joelkuiper: What does process-documents return?

joelkuiper13:12:53

the org.httpkit.server.AsyncChannel

joelkuiper13:12:09

where a json is pushed on when it’s done

joelkuiper13:12:43

the gist of it

(defn async
  "Long-polling/Comet handler.
   Takes a core.async chan and sends the response when available"
  [request c]
  (http/with-channel request channel
    (async/go-loop [v (<! c)]
      (http/send! channel v)
      (close! c))
    (http/on-close channel (fn [_] (async/close! c)))))

joelkuiper13:12:19

hmm so that should return false, can I override it somehow?

joelkuiper13:12:30

or do you think it might be some other middleware?

joelkuiper13:12:48

full stack

java.lang.Thread.run              Thread.java:  745
           java.util.concurrent.ThreadPoolExecutor$Worker.run  ThreadPoolExecutor.java:  617
            java.util.concurrent.ThreadPoolExecutor.runWorker  ThreadPoolExecutor.java: 1142
                          java.util.concurrent.FutureTask.run          FutureTask.java:  266
          java.util.concurrent.Executors$RunnableAdapter.call           Executors.java:  511
                           org.httpkit.server.HttpHandler.run         RingHandler.java:   91
                  compojure.api.middleware/wrap-components/fn           middleware.clj:   79
                dre.datahub.middleware/wrap-internal-error/fn           middleware.clj:   40
                       dre.datahub.middleware/wrap-context/fn           middleware.clj:   35
       ring.middleware.x-headers/wrap-content-type-options/fn            x_headers.clj:   53
              ring.middleware.x-headers/wrap-frame-options/fn            x_headers.clj:   38
             ring.middleware.x-headers/wrap-xss-protection/fn            x_headers.clj:   71
            ring.middleware.not-modified/wrap-not-modified/fn         not_modified.clj:   52
      ring.middleware.default-charset/wrap-default-charset/fn      default_charset.clj:   26
            ring.middleware.content-type/wrap-content-type/fn         content_type.clj:   30
                    ring.middleware.resource/wrap-resource/fn             resource.clj:   28
ring.middleware.absolute-redirects/wrap-absolute-redirects/fn   absolute_redirects.clj:   36
                      ring.middleware.cookies/wrap-cookies/fn              cookies.clj:  161
                        ring.middleware.params/wrap-params/fn               params.clj:   64
    ring.middleware.multipart-params/wrap-multipart-params/fn     multipart_params.clj:  117
          ring.middleware.nested-params/wrap-nested-params/fn        nested_params.clj:   84
        ring.middleware.keyword-params/wrap-keyword-params/fn       keyword_params.clj:   35
                      ring.middleware.session/wrap-session/fn              session.clj:  102
                          ring.middleware.flash/wrap-flash/fn                flash.clj:   35
                      ring.middleware.webjars/wrap-webjars/fn              webjars.clj:   34
      ring.middleware.format-response/wrap-format-response/fn      format_response.clj:  185
                                cheshire.core/generate-string                 core.clj:   21
                                cheshire.core/generate-string                 core.clj:   32
                                   cheshire.generate/generate             generate.clj:  148
com.fasterxml.jackson.core.JsonGenerationException: Cannot JSON encode object of class: class org.httpkit.server.AsyncChannel: /0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:57095
    originalMessage: "Cannot JSON encode object of class: class org.httpkit.server.AsyncChannel: /0:0:0:0:0:0:0:1:3000<->/0:0:0:0:0:0:0:1:57095”

joelkuiper13:12:52

mostly from ring-defaults

juhoteperi13:12:58

Quite hard to see from stack trace is the r-m-f middleware that is causing problems is the one from compojure-api or not

joelkuiper13:12:25

looks like it might’ve been duplicate from the general middleware, let me check

joelkuiper13:12:35

bit unsure what the order of these things is

joelkuiper13:12:09

yep was a duplicate wrap-formats

danielgrosse13:12:06

Are there cases known, that a for not working as expected? I have a loop

(for [[reg-uri event-chan]  (:sub-on-call connection)
      :let [req-id (clj-wamp.core/new-rand-id)]]
  (println reg-uri req-id))
which works in the REPL. But in the function where it is integrated, it doesn’t do anything. (count map) before the loop returns 2 so I don’t see a reason, why it’s not working.

joelkuiper14:12:09

@juhoteperi: thanks simple_smile seems like it was a bug on my side with the duplicate format; different question is it possible to add the schema for the return just as documentation, without coercion?

joelkuiper14:12:10

okay, just checking

ikitommi14:12:11

@joelkuiper: should be. just add is under :swagger

joelkuiper14:12:20

as what key?

joelkuiper14:12:35

hmm conflict!

joelkuiper14:12:47

i’m still on 0.2.13 btw

joelkuiper14:12:33

for compojure api, 2.1.3 for ring-swagger

ikitommi14:12:38

not sure what version is that. but as the :swagger works, add :swagger {:responses {200 {:schema dm/AnnotateResponse}} and you should get the swagger-docs

roelof16:12:30

I heard a lot about boot instead of leiningen. As a beginner can I better stick with leiningen or make the transition into boot

meow16:12:59

@roelof: boot is excellent, but leiningen is far from dead - I would advise you to plan to learn both

roelof16:12:40

oke, then first I stick with lein so I can continue learning clojure as a beginner

roelof16:12:49

and later look at boot

roelof16:12:33

@meow: any tutorails you can recommend for a beginner in boot

meow16:12:43

@roelof: no, I would just google and see what comes up - the boot folks are extremely supportive and there is #C053K90BR here as well

niwinz16:12:08

Personally i'm switched off from boot because is too much slow 😞

martinklepsch16:12:40

@niwinz: any public projects I could look at where boot is to slow?

martinklepsch16:12:25

@niwinz: in case you have the project still setup I'd be very interested in seeing some numbers :)

roelof16:12:34

@meow: thanks for the answers

niwinz16:12:33

I switched some my projects to boot and for example executing the uberjar is almost 3x slower than doing the same task in lein... But lamentably now, I don't have any project using boot..

martinklepsch16:12:30

@niwinz: uberjar perf has been improved dramatically with 2.5.0 (currently only snapshot releases)

niwinz16:12:52

Nice to hear that!

alexmiller16:12:36

It would be great to see a large response on the survey so we can take the pulse of the community! Thanks...

meow16:12:55

@alexmiller: So I filled out the first page, clicked Next, and it put me back on the first page with all my answers wiped out. 😞

alexmiller16:12:22

I made one question change on pg 1 - maybe that messed up people in progress

alexmiller16:12:30

if so, my apologies!!

meow16:12:02

@alexmiller: no problem, just wanted you to know

meow16:12:10

should I try again?

mdaines16:12:35

I hit the back button, it recovered my answers, then when I hit next it went to page two.

gabe16:12:27

@alexmiller: missed page 2 as well

jaen16:12:43

Oooh, nice, first state of Clojure I can actually fill in having finally done real Clojure work this year : D

bendlas17:12:19

@dnolen: I've been trying to apply core.logic to output of tools.analyzer, but the copying walk* in ground checking is really a big roadblock for the kind of massively interlinked data, the analyzer produces ...

bendlas17:12:54

would you consider that a use case worth supporting?

roelof17:12:56

@alexmiller: how do you "store" the answers a page. When I ready to learn web development Im also thinking of using these wizards/multipage forms ?

jaen17:12:00

I suppose "How long have you been using Clojure, ClojureScript, or ClojureCLR?" means seriously using the language not just "hey, I can write quicksort in that", right?

alexmiller17:12:26

whatever makes sense for you

roelof17:12:22

IM using clojure for some 2 - 3 weeks now

jaen17:12:57

I guess, I'll go with 1 year then; I've been following Clojure since 1.3, but didn't do anything more than simple algorithms until this year.

roelof17:12:05

I only did the clojure koans and I think the half of the easy exercises of 4clojure

roelof17:12:26

So I have to develop a clojure and FP mind-set

sveri19:12:04

Hi I am trying out schema...but, one thing that bugs me is that the names of the defs are so long like "defschema" and "required-keys" and so on. Is there a way to shorten them? I tried a simple (def ds s/defschema) but it fails with a compiler exception: CompilerException java.lang.RuntimeException: Can't take value of a macro: #'schema.core/defschema

alex.hall19:12:10

@sveri: You'd have to do that as a macro: (defmacro ds [& body] `(s/defschema [email protected]))

alex.hall19:12:53

But I personally would favor legibility over abbreviation, i.e. use the real names

sveri19:12:49

@alex.hall: Thanks, should have thought of them^^. They just take up so much space, especially defschema and required-key...they take most of the lines without providing anything useful

alex.hall19:12:45

Fair enough. I just think that such abbreviations lead to unmaintainable code, especially in a team environment.

jaen19:12:05

You don't have to use defschema thought. I do (def SchemaName {:key s/Int}) and it just works.

sveri19:12:18

I agree. My plan is to keep them in one namespace, make them private, so they don't leak out of my schema definitions namespace

jaen19:12:38

Similarly for required-keys - you don't have to use it for :keyword keys, they are required by default. Unless you have string keys, then tough luck.

sveri19:12:01

@jaen: Well, thats better...awesome, thank you simple_smile

jaen19:12:56

Actually it's somewhat annoying to do the reverse - make optional keyword keys. For some reason schema doesn't accept any option to validate to flip the behaviour.

jaen19:12:00

You have to postwalk them.

jaen19:12:25

And not just any postwalk, since that won't understand most of schema's wrappers around values.

jaen19:12:42

I asked about that a while ago here, let me dig that up.

jaen19:12:30

Also, one downside to not using defschema, the schema name isn't assoc'd into metadata.

sveri19:12:54

I agree...thats a disadvantage, have not thought of that

jaen19:12:59

Though I'm unsure what that means in practice (maybe worse error messages?).

jaen19:12:53

@sveri: here's the code for making all keys optional:

(ns scrabble.common.utils.schema
  (:require [schema-tools.core :as st]
            [schema-tools.walk :as st-walk]))

(defn with-optional-keys [schema]
  (st-walk/walk schema
                (fn [x]
                  (let [y (with-optional-keys x)]
                    (if (and (map? y) (not (record? y)))
                      (st/optional-keys y)
                      y)))
                identity))

sveri19:12:39

@jaen thanks, I'll keep it and see when I need them

jaen19:12:44

Schema tools in general seem pretty handy

bigkahuna19:12:16

Had a great time at ClojureX. Already looking forward to ClojureX 2016.

jaen19:12:48

Were the talks recorded perchance? Though looking at ClojureTV I guess the answer is "no".

alexmiller20:12:04

ClojureX is put on by Skills Matter and they usually host talks somewhere other than the ClojureTV channel

alexmiller20:12:48

I think they usually are recorded though - you might want to ask on #C075TNSSC

jaen20:12:48

@alexmiller: thanks for the channel pointer, someone linked to Skills Matter channel with the talks yesterday. it says I have to login, but hopefully an account is free.

hlship20:12:01

About the Survey ... question 17 is a bit odd; it's asking us to evaluate the priority of improvements, but does not provide any idea of what those improvements might be. "Startup time" and "Runtime performance" are obvious ... but what improvements are being considered for "Namespaces" or "More compiler control"?

alexmiller20:12:48

nothing specific, just general areas

alexmiller20:12:20

Nicola suggested the latter one, really in regards to more control over how var linking, inlining, etc is done

alexmiller20:12:38

we have no specific plans to do that, but that was the idea

alexmiller20:12:06

re namespaces, there have been ideas floated about immutable namespaces and things of that nature in the past

jaen20:12:06

Hah, I think that depends on how you interpret things. For namespaces I compared what Dunaj project did to current state of art in Clojure, which made me rate it low. And I took "more compiler control" to being able to tune optimisations for example.

alexmiller20:12:40

@jaen those both seem like reasonable interpretations

rcanepa20:12:13

@jaen: accounts are free. I am watching one video right now.

alexmiller20:12:31

@hlship: in the past there has been some free form question about adding features to Clojure. the intent here is to replace that with something that gives better and more actionable data (by both not listing things we have no intent of doing and listing specific priority areas)

jaen20:12:50

Incidentally, Dunaj's modularisation and restructuring on API seemed a fairly interesting idea, what does core think of that?

jaen20:12:04

@rcanepa: good to know it's free, thanks!

alexmiller20:12:10

@jaen the stuff in Dunaj are interesting ideas but we tend to work starting from a specific problem

alexmiller20:12:28

so the question is what problem needs to be fixed?

alexmiller20:12:54

if the problem is startup time, then namespace reorganization might be one solution

alexmiller20:12:09

but so might lazy vars or using invokedynamic for var invocation or parallelization or something else

alexmiller20:12:12

if the problem is related to organization, that's a different set of possible solutions

alexmiller20:12:23

of which restructuring the api is one answer

hlship20:12:32

Was just looking at Clojure 1.8, letting IntelliJ decompile the compiled functions.

hlship20:12:32

I noticed that the function classes still create references to Vars as static fields, even if those are Vars for functions that will be statically invoked.

hlship20:12:43

Probably minor, but this is memory and execution time that could be shaved. Are these public fields being left around intentionally?

alexmiller20:12:10

Rich plans to work on cleaning that up in 1.9

jaen20:12:31

@alexmiller: gotcha. I've read the Dunaj's docs and I think the arguments re: API organisation make sense. I do understand though there might be different solutions to the startup time part other than modularisation, I don't know enough of how Clojure works to have an opinion, since I've been doing it more seriously only for a year.

lumengxi21:12:01

which channel should we ask general questions about Clojure web development? not clojurescript related, more on backend

meow21:12:07

@lumengxi: this one is fine to start with

sveri21:12:23

Hi. using prismatic schema I have a map in a def like this: (def foo {:name "init-aval" :bar "bar"}). Now I want to define a schema for this. Can I define schemas for defs?

dmitrig0121:12:10

@sveri: sure, (def foo (s/validate yourschema {:name .... }))

zane21:12:36

Anyone have examples of client libraries (i.e. libraries that wrap a web API) that they love? I'm wondering about best practices.

sveri21:12:43

@dmitrig01: Does it validate at runtime too?

dmitrig0121:12:31

@sveri: schema is a runtime-only tool

zane21:12:32

@sveri: Look at the docstring for s/validate.

sveri21:12:43

Ah, I remember...you could turn it off and enable it only in dev...thanks everyone

sveri22:12:46

Ok, another schema question. Can I define static values like 1?

sveri22:12:03

So I have a map like this {:default 1}?

sveri22:12:41

I found ther is (eq val). Is that the correct one to choose?

hkjels22:12:33

I have a list ({:employee/name Timmy}), why is it that, when I peek at this list I get an java.lang.ClassCastException exception?

hkjels22:12:41

Is it println that’s trying to cast it, but is not able to?

hkjels22:12:18

and I don’t see why println whould have a problem with that map

waffletower23:12:56

I enjoyed the Clojure community survey. I was surprised to see no mention of "debugging tools" in the survey though ("error messages" was the closest fit). I mentioned this in my final comments.