#clojure log - Jun 08 2015

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

2:15 chr15m: Hello! Is it an uncommon thing for people to invoke cljsbuild to build for a static client-side-only web app? For example an app that will run in a Phone's browser with no server component, or an app that lives on a github pages page, or one that talks to some non-clojure backend.

2:15 I can't figure out how to easily get cljsbuild to do this by default. Everything seems to be structured around creating an "uberjar".

2:53 TEttinger: chr15m, I'm curious about this too

2:53 I'm sure there's a way, unless cljs specifically needs a server side component for some features, but I don't think it does

2:59 oddcully: wouldnt `lein cljsbuild once <prod/min/whateveryoupicked>` generate you the stuff to send to your docroot?

3:07 chr15m: oddcully: i am using the reagent template and it doesn't include such a build identifier. it has one called 'app' but that builds in development mode without doing the optimisations or minification. i guess i'll just have to write my own.

3:10 oddcully: chr15m: copy that one down and change the optimizations to advanced. this at least gives me one blob of a .js file with the figwheel-template that runs fine with a python SimpleHttpServer (i am using rum btw)

3:11 chr15m: oddcully: was just doing that and got the same result, thanks :)

3:11 oddcully: and btw there is also #clojurescript

3:11 chr15m: oh! sorry, yes.

3:11 i will check out rum too

3:11 oddcully: no problem at all

3:11 just to let you know

3:27 zot: to turn {:a [1 2 3], :b [4 5 6]} -> [:a 1] [:a 2] [:a 3] [:b 4] [:b 5] [:b 6], i have (for [[k vs] m, v vs] [k v]); is there something better? (feels like for loops often should be last resort…)

3:32 TEttinger: ,(mapcat (fn [k vs] mapcat (partial vec k) vs) {:a [1 2 3], :b [4 5 6]})

3:32 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: sandbox/eval25/fn--26"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: sandbox/eval25/fn--26"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.core$map$fn__4551 invoke "core.clj" 2...

3:32 TEttinger: ,(mapcat (fn [k vs] (mapcat (partial vec k) vs) {:a [1 2 3], :b [4 5 6]})

3:32 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

3:32 TEttinger: gah

3:32 ,(mapcat (fn [k vs] (mapcat (partial vec k) vs)) {:a [1 2 3], :b [4 5 6]})

3:32 clojurebot: #error {\n :cause "Wrong number of args (1) passed to: sandbox/eval73/fn--74"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (1) passed to: sandbox/eval73/fn--74"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 32]\n [clojure.core$map$fn__4551 invoke "core.clj" 2...

3:33 zot: TEttinger: i feel your pain :)

3:33 TEttinger: ,(mapcat (fn [[k vs]] (mapv (partial vector k) vs)) {:a [1 2 3], :b [4 5 6]})

3:33 clojurebot: ([:a 1] [:a 2] [:a 3] [:b 4] [:b 5] ...)

3:36 TEttinger: zot: ^

3:36 zot: thanks for the persistence :) as a medium-seasoned clojure user, do you find that more readable than the for version? i suspect that my many years of C-ish languages allows me to read the for loop more readily, so i can't ditch my own bias :)

3:36 errr

3:36 i'm the medium seasoned

3:36 bad rewording

3:36 TEttinger: I think m wasn't actually declared in the for loop

3:36 so it was kinda hard to see what you meant

3:37 zot: it is, before the comma

3:37 but it's just an m, and hard to see

3:37 TEttinger: but what is m's value?

3:37 zot: a map, just like the data example i wrote before

3:37 TEttinger: oh ok

3:38 then vs?

3:38 zot: i guess my idiom: if i have a v, and a sequence of vs, i use vs for the sequence

3:38 as in, plural of v

3:38 TEttinger: yeah, I get that, but the thing is, there's a "to turn" but no "(def ..."

3:39 so I don't know what the values you're using for m and vs are

3:40 zot: gotcha. should have been (def m <LHS of the expr>). next time i'll gist it :)

3:40 TEttinger: yah, no prob

3:40 I still don't actually know what you meant by vs there though

3:41 it's a second loop, effectively...

3:42 zot: yep, you get it. double loop iterating over keys, then values to unroll the value sequences.

4:57 mercwithamouth: does anyone here practice writing data structures from scratch over and over? say if studying for a class. repetition?

5:15 wasamasa: I'm pretty sure one of the reasons of providing a wealth of built-ins and records and easy access to java data types was to not have to do that again :>

5:16 mercwithamouth: wasamasa: lol i just mean as a method of learning...i'm wondering how well repetition works with becoming a better developer =P

5:17 wasamasa: I'm sure that's an individual thing

5:20 amalloy: mercwithamouth: doing the same thing over and over is a good way to build muscle in your fingers, but it's hard to believe you really learn a lot by implementing the same data structure in the same language more than twice

5:20 the first time, you're learning how it works. the second time, you're fixing all the mistakes you made the first time and clarifying your thoughts. after that, what are you gaining?

5:20 find something new to do

5:58 mercwithamouth: what in the hell? (reduce [r x] (+ r (* x x))) [1 2 3])

5:59 pepperpot: Download either SEO Analyzer full script, Website Value Calvulator Full Script, or Ajax Star Reviews script, all fully tested and working, download them for your website, you're welcome! https://www.criosphinx.net/forum/forumdisplay.php?fid=20

6:00 oddcully: yay! calvulation for everyone

6:00 mercwithamouth: lol

6:02 TEttinger: mercwithamouth: ? what about (reduce [r x] (+ r (* x x))) [1 2 3])

6:02 is [r x] your function there?

6:03 mercwithamouth: TEttinger: i'm trying to figure out...for say the first iteration what gets assigned to r and whats assigned tox

6:03 oddcully: ,(doc reduce)

6:03 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i...

6:03 TEttinger: ,(reduce (fn [r x] (+ r (* x x))) [1 2 3])

6:03 clojurebot: 14

6:03 amalloy: looks like he forgot the (fn ...) wrapping around that

6:03 TEttinger: ninja!

6:03 amalloy: it's just sum-of-squares, implemented somewhat opaquely

6:04 and badly, i guess, because it only works if the first item in the list is either 0 or 1

6:04 TEttinger: hehe

6:04 mercwithamouth: hmm also good to know

6:04 TEttinger: ,(reduce (fn [r x] (+ r (* x x))) [3 4 5])

6:04 clojurebot: 44

6:04 TEttinger: ,(reduce (fn [r x] (+ r (* x x))) 1 [3 4 5])

6:04 clojurebot: 51

6:04 TEttinger: ,(reduce (fn [r x] (+ r (* x x))) 0 [3 4 5])

6:04 clojurebot: 50

6:04 TEttinger: hm that seems to work

6:04 amalloy: you want 0 there

6:05 mercwithamouth: o_O

6:05 TEttinger: wasn't sure if I wanted additive or multiplicative identity,or to fall asleep

6:05 mercwithamouth: my lisp virgin eyes

6:05 amalloy: they all "work" in that they evaluate to something, but only your last one evaluates to 3^2 + 4^2 + 5^2

6:05 mercwithamouth: i think i have to write that one on paper and do the steps

6:06 TEttinger: the easy way to get the steps:

6:06 &(reductions (fn [r x] (+ r (* x x))) 0 [3 4 5])

6:06 lazybot: ⇒ (0 9 25 50)

6:06 mercwithamouth: ahhHH

6:06 TEttinger: because 25 == 9 + 16

6:06 mercwithamouth: i assume that works for all lisp functions? cool

6:07 TEttinger: reductions is just reduce that keeps intermediate steps in the sequence it returns

6:07 mercwithamouth: well wait.. 'reductions' and not 'reduce' still cool so you can see each value returned as it progresses

6:07 TEttinger: instead of only returning the last thing

6:07 oddcully: ,(reductions + [1 2 3])

6:07 clojurebot: (1 3 6)

6:07 mercwithamouth: nice....

6:08 well that clears that up. now i see =P

6:08 alright..going to play with reduce for the night...or well morning

6:08 ionthas_: I have a function that mutates a vector with a given provability. I want to implement a test to know if it's working right. Any ideas in how to test that?

6:08 (I'm using midje)

6:10 kasterma: ionthas_: Run the operation many many times, see the fraction of times the modification happens is approximately correct.

6:10 If running on continuous integration (don’t want false positives) fix the random seed.

6:12 ionthas_: thanks kasterma, good point with the random seed.

6:41 crocket: After learning clojure, I'm afraid to deal with javascript and java again.

6:41 I'm afraid that other programmers mutate my javascript objects.

6:42 There is almost no guaranteed invariant that I can depend on in javascript.

6:44 katratxo: crocket: try https://swannodette.github.io/mori/

6:46 spacepluk: crocket: you can also freeze the objects I guess

6:47 it's slow though

6:58 thedavidmeister: hi

6:58 i'm new to clojure and getting some cryptic errors

6:59 anyone have a bit of time to help?

6:59 oddcully: thedavidmeister: put your code and error on refheap.com or some other place so someone can have a look

7:00 thedavidmeister: oddcully: kk

7:01 oddcully: https://www.refheap.com/102286

7:05 oddcully: any idea what i did wrong?

7:09 Kneiva: thedavidmeister: what "docker ps..." is supposed to return? and is that directly applicable to "docker rm"?

7:13 thedavidmeister: Kneiva: docker ps returns (fa5e01a1cd46 403d6b4bd8a4)

7:13 Kneiva: when i println - which are hashes of docker containers

7:15 Kneiva: if i do (docker "rm" "-f" "fa5e01a1cd46") that works

7:16 crocket: katratxo, That's not going to fix javascript.

7:16 spacepluk, That's also not going to fix javascript.

7:16 In a multi-person project, javascript is going to leak.

7:16 oddcully: thedavidmeister: well i don't know conch. the error would indicate to me, that the result of main should be an number and your docker function there returns an obj. can you try (:exit-code (docker ...)) ?

7:18 thedavidmeister: hmm (docker "rm" "-f" '("f772acef31c3" "403d6b4bd8a4")) breaks

7:19 Kneiva: thedavidmeister: was just suggesting to try that =)

7:19 thedavidmeister: is conch a normal way to be trying to do shell stuff?

7:19 or is there a different library i should look at?

7:20 oddcully: hmm, what is :exit-code supposed to do?

7:21 Kneiva: these docs made it look like i could use a sequence https://github.com/Raynes/conch

7:21 Kneiva:

7:21 oddcully: under the assumption, that you docker call there is the last thing in your code, it's return value would be "the return"

7:21 thedavidmeister: Kneiva: or did i just mis-read it?

7:21 oddcully: looking at the GH page there suggests, that the returned object there holds an :exit-code

7:21 so (:exit-code (...)) would fetch that out of it

7:22 thedavidmeister: oddcully: (println (:exit-code (docker "rm" "-f" '("f772acef31c3" "403d6b4bd8a4") {:throw false})))

7:22 oddcully: i got nil back

7:23 Kneiva: thedavidmeister: does (docker "rm" "-f" "f772acef31c3" "403d6b4bd8a4") work?

7:24 thedavidmeister: Kneiva: it did

7:24 Kneiva: so how do i turn a sequence into a bunch of string arguments?

7:25 Kneiva: apply

7:26 oddcully: (apply (partial docker "rm" "f") theresult)

7:28 Kneiva: &&(+ 1 2 [3 4]) &&(apply + 1 2 [3 4])

7:28 lazybot: java.lang.RuntimeException: Unable to resolve symbol: & in this context

7:28 Kneiva: no, how was it?

7:29 ,(+ 1 2 [3 4])

7:29 clojurebot: #error {\n :cause "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentVector cannot be cast to java.lang.Number"\n :at [clojure.lang.Numbers add "Numbers.java" 128]}]\n :trace\n [[clojure.lang.Numbers add "Numbers.java" 128]\n [clojure.lang.Numbers add "Numbers.java" 3640]\n [sandbox$eval25 invoke...

7:29 oddcully: only one & or , or ##

7:29 Kneiva: ,(apply + 1 2 [3 4])

7:29 clojurebot: 10

7:31 thedavidmeister: kk, give me a sec

7:33 ah cool

7:33 (apply (partial docker "rm" "-f") (docker "ps" "-aq" {:seq true}))

7:33 totally worked

7:33 woo

7:33 thanks

7:34 so, is there something better than conch around for doing shell stuff?

7:35 oddcully: (inc Kneiva)

7:35 lazybot: ⇒ 1

7:37 Kneiva: wohoo \p/

7:39 thedavidmeister: ah, i g2g

7:39 thanks for helping

7:39 oddcully: well there is clojure.java.shell. but conch looks actually good to me

7:40 thedavidmeister: (inc Kneiva)

7:40 lazybot: ⇒ 2

7:40 oddcully: will definetly have to play around a bit with it

7:40 thedavidmeister: (inc oddcully)

7:40 lazybot: ⇒ 9

7:58 ksaua: Hi, is there a function that will do the following: (somefunc (1 2 3 4 5)) = ((1 2) (2 3) (3 4) (4 5)) ?

7:59 oddcully: ksaua: ,(let [p [1 2 3]] (zipmap p (rest p)))

8:01 oh you want lists. ,(let [p [1 2 3]] (map list p (rest p)))

8:01 ksaua: yeah, sorry

8:01 Hi, is there a function that will do the following: (somefunc [1 2 3 4 5]) = [[1 2] [2 3] [3 4] [4 5)] ?

8:01 :)

8:02 oddcully: s/list/vector/

8:03 schmir: ksaua: partition-all

8:05 or rather partition

8:05 oddcully: yeah partition

8:06 ,(partition 2 1 [1 2 3])

8:06 clojurebot: ((1 2) (2 3))

8:06 ksaua: thanks!

8:18 oddcully: shouldn't give me (parition 2) back a transducer in 1.7?

8:19 puredanger: I think only partition-all

8:20 oddcully: true

9:39 bja: can I pass in a DataSource (ala c3p0 connection pool) to clojure.java.jdbc/with-db-transaction?

9:40 justin_smith: bja: I've had issues with c3p0 and transactions, but it could have been a configuration issue, we never got around to sorting it out

9:42 bja: c3p0 has been working okay for me in most regards, but I'm trying to use prepared statements for a server-side cursor with postgres

9:42 and now I think I'm passing the wrong thing into with-db-transaction

9:43 oh

9:43 that's nasty. just figured out from reading the source, that add-connection is how you get something with-db-transaction wants to use

9:44 justin_smith: it's just fundamentally incompatible with pooling?

9:45 bja: well, it seems as though you have to check out a connection first

9:46 pass that into add-connection to create a map that with-db-transaction understands

9:46 this seems to work

9:46 justin_smith: weird!

9:46 thanks, that should be useful

9:50 joegallo: i'm just some guy in the peanut gallery, but that doesn't sound quite right to me... we've been happily using c3p0 with c.j.jdbc for quite some time. are you trying to use with-db-transaction outside the context of a with-db-connection or something? because it seems to me that with-db-connection does the add-connection type stuff on your behalf.

9:52 or, of course, it's also possible i don't understand your use case, etc.

9:54 justin_smith: joegallo: oh - so your method would be (with-db-connection (with-db-transaction ...))

9:56 crocket: Is there an alternative to gogs and gitlab written in clojure?

9:56 or haskell?

9:56 Neither Go nor Ruby is my preference.

9:57 ionthas_: I'm looking for a fast random number generator for clojure. Anyone knows if there is some SFMT implementation?

9:57 sg2002: bja: Here's what I used: https://www.refheap.com/102289

9:58 justin_smith: ionthas_: I don't know, but I'd look for the java impl (which I am sure must exist) and use that via interop

9:58 crocket: It seems I have bitbucket for private repos.

9:58 sg2002: bja: As far as I remember you need make-pool? false or with-db would try creating a new pool.

10:18 H4ns: i knew i've asked this same question a few months ago, but maybe it has changed since then. i find myself spending obscene amounts of time whenever i see conflicts in my :dependencies. we've moved to depending on all libraries explicitly which has made the process a little more manageable, but it is still ours how running "lein deps :tree" and then creating more exclusions and dependencies

10:19 it is so painful. any cure in sight?

10:19 with :pedantic? abort, of course. maybe we should just switch that off and live on the other edge.

10:29 * Fare wonders if there are bazel rules for clojure yet

10:50 kaffeeboehnchen: Hi. :)

10:51 How can I make '("abc" "def") to "abcdef"?

10:51 stuartsierra: kaffeeboehnchen: apply str

10:52 kaffeeboehnchen: stuartsierra: nice, thanks! :)

10:53 stuartsierra: You're welcome.

10:54 gfredericks: does anybody know what it is about cider/clojure-mode that doesn't parse foo' correctly and if it's fixable?

10:55 maybe it's not foo'

10:55 it's something to do with funny-quotes though

10:57 maybe it's a syntax highlighting thing

10:57 certainly :foo'bar seems to be highlighted wrong

10:58 this probably only matters when test.check is generating keywords for you

10:58 (def foo'bar nil) also highlights wrong

10:58 presumably this has nothing to do with cider

11:17 clgv: hi, which leiningen plugin do you recommend for the "expectations" library?

11:19 there are at least "lein-autoexpect" and "lein-expectations"

11:44 Shayanjm: has anyone done distributed computing with clojure here?

11:44 trying to figure out the best way to distribute 950k API requests to a cluster with throughput throttling

11:54 justin_smith: Shayanjm: I don't think I know the answer, but is that 950k a second? a day?

11:55 Shayanjm: justin_smith: 950k total. It needs to be throttled to x requests/second for each 'account' used to query

11:55 i'm thinking i'll set up each worker machine with a separate API account so we can throttle to just the box

11:55 I think it's something like 20 req/sec

11:56 the question is - should I just split up the 950k requests at the top of the funnel (i.e: 950k/# of worker machines), or should I just add each query to a queue and have the machines grab them in round-robin fashion?

11:56 There's overhead in reading/writing to a queue, so it might make sense to batch them, but I don't know if I'm eating considerable overhead somewhere with that approach

12:04 justin_smith: Shayanjm: you don't need round robin - with the right queue they should be able to grab the items (pull) as needed

12:04 Shayanjm: That's true. it doesn't necessarily have to be round-robin since order doesn't necessarily matter

12:04 the results will be deduped somewhere anyway

12:05 justin_smith: right, round robin would be a way to split them up when pushing

12:05 but pull can use the processes more efficiently

12:06 kaffeeboehnchen: what is the best way to get the values in the if? https://paste.xinu.at/ljNj/

12:06 justin_smith: my naive / straightforward version would be to have a gateway machine that just queues requests and provides them to workers as the workers pull tasks

12:07 Shayanjm: then upgrade to batching as an optimization and see what empirically has the best throughput

12:07 Shayanjm: fair enough. Thanks justin_smith

12:07 justin_smith: kaffeeboehnchen: why are you calling the first (get-box ...) result with the second as its arg?

12:08 I mean that could be valid but it looks weird

12:08 was that meant to be a do?

12:09 kaffeeboehnchen: justin_smith: well, thats a ) I forgot

12:09 wait, the first (get-box) does not get the second

12:10 justin_smith: kaffeeboehnchen: that's false

12:10 kaffeeboehnchen: justin_smith: sorry, i cant follow you

12:10 justin_smith: the parens clearly show that the first (get-box ...) is called as a function, with the result of the second (get-box ...) as an arg

12:11 perhaps instead of ( (get-box ...) (get-box ...)) you meant (do (get-box ...) (get-box ...))

12:11 kaffeeboehnchen: ah, ok

12:11 thanks! :D

12:11 justin_smith: or alternatively (if ... (get-box ...) (get-box ...))

12:11 wink: why doesn't this work? (def x (java.util.HashMap<Integer, Integer>.))

12:12 justin_smith: wink: generics are a lie

12:12 they do not exist

12:12 wink: I know, I tried to test something

12:12 oddcully: like the cake

12:12 justin_smith: wink: you can't test them because they don't exist

12:12 wink: damn.

12:12 justin_smith: I mean sure you can use the java compiler if you want to use them

12:12 kaffeeboehnchen: justin_smith: so, i fixed that, how do i get the results now as a return for get-body?

12:12 justin_smith: wink: but on a bytecode level there is no such thing

12:12 wink: I ususally skip making a bogus 20line test program in java

12:13 justin_smith: heh

12:13 wink: but in this case I have to :P

12:13 justin_smith: wink: there is nothing to test though, there is nothing in the compiled output that corresponds to a generic

12:13 wink: hmm

12:13 clojurebot: Titim gan éirí ort.

12:13 wink: it's about Integer, Integer and int, int in this case.

12:14 justin_smith: kaffeeboehnchen: the result of get-body will be the lazy-seq generated by for, which will be made up of calls to get-box

12:14 wink: so either there really is not a difference... or it's tedious

12:14 thanks anyway

12:14 justin_smith: wink: int cannot be used in a HashMap

12:14 wink: that explains a lot :)

12:14 thanks even more

12:14 justin_smith: only Object can be used as a key or val :)

12:14 so Integer would be auto-substituted if you tried to use an int

12:15 wink: see, that's what a quick repl line usually creates insight for

12:15 justin_smith: ,(type (ffirst (java.util.HashMap. (int 1) (int 1))))

12:15 clojurebot: nil

12:15 justin_smith: hmm

12:16 TimMc: H4ns: Is your goal just to manage unexpected changes in dependencies?

12:16 justin_smith: ,(type (ffirst (into {} (java.util.HashMap. (int 1) (int 1)))))

12:16 clojurebot: nil

12:16 justin_smith: ahh!

12:16 ,(type (ffirst (into {} (doto (java.util.HashMap.) (.put (int 1) (int 1)))))))

12:16 clojurebot: java.lang.Integer

12:17 justin_smith: wink: ^ does that help?

12:17 wink: not more than what you previously wrote, because it was enough ;)

12:17 justin_smith: ahh, OK

12:17 wink: autoboxing and unboxing still surprises me a little at times, even after all those years

12:17 justin_smith: it's a little weird

12:18 wink: 8/10 it's smarter than I'd expect. at least

12:22 justin_smith: kaffeeboehnchen: also, after taking another look at your code I wonder if you know about let?

12:22 kaffeeboehnchen: because the code could be simpler imho if you used let to bind things like ((nth positions i) :y) or at least (nth positions i)

12:23 wasamasa: kaffeeboehnchen: why are you using str on an side-effectful function?

12:24 guess it's for debugging what happens

12:28 Shayanjm: justin_smith: what're the ramifications of clojure's STM in a distributed environment? At that point it'd make more sense to write to a database rather than keep things in memory on worker nodes, right?

12:28 and try to sync/stitch all the data from the workers?

12:30 justin_smith: Shayanjm: yeah, stm is per vm, and doesn't really help across process boundaries

12:31 Shayanjm: Yeah that's what I figured

12:31 there's stuff like avout which offers a distributed STM

12:31 but I'm thinking that'd introduce more overhead than it's really worth in this case

12:32 kaffeeboehnchen: wasamasa: I am a noob :D

12:32 justin_smith: I'd be happy to use let in that case if you can show me how. see ^

12:32 justin_smith: Shayanjm: well, having a single box control the queue is a compromise - stm can help manage the queue, and then all the other boxes work in isolation

12:33 kaffeeboehnchen: wasamasa: Btw, not using str anymore already ;)

12:33 justin_smith: ,(let [a 0 b 1] (+ a b)) ; kaffeeboehnchen

12:33 clojurebot: 1

12:33 justin_smith: (doc let)

12:33 clojurebot: "([bindings & body]); binding => binding-form init-expr Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

12:33 justin_smith: kaffeeboehnchen: it's how we do "local variables" (though in our case they can't vary)

12:34 kaffeeboehnchen: I'll try to change it. thanks :)

12:34 Shayanjm: Cool, thanks justin_smith

12:36 kaffeeboehnchen: ok, one strange thing … with (count (re-matches #"[0-9]" (str (nth hash i))))) I get an integer, but (> 0 (count (re-matches #"[0-9]" (str (nth hash i)))))) is always false for me?

12:36 justin_smith: kaffeeboehnchen: ##(> 0 9)

12:36 lazybot: ⇒ false

12:36 justin_smith: ,(> 9 0)

12:36 clojurebot: true

12:37 kaffeeboehnchen: m(

12:37 justin_smith: polish notation takes a little while to get used to for the comparators (it did for me)

12:37 kaffeeboehnchen: this might help ##(> 9 2 0 -2)

12:37 lazybot: ⇒ true

12:37 justin_smith: so think of that version

12:37 kaffeeboehnchen: thanks!

12:37 justin_smith: ,(< -100 0 100 1000)

12:37 clojurebot: true

12:38 kaffeeboehnchen: sorry, I get confused all the time. VB.NET and python in the job, c#, c++ and java at the school. :(

12:38 maseb: what’s the diff between clojurebot and lazybot?

12:39 ToxicFrog: maseb: one is the real one and the other is its evil twin from an alternate timeline.

12:39 We can't figure out which, so we just let them both stick around.

12:39 maseb: !

12:39 A calculated risk.

12:39 justin_smith: maseb: they both do clojure eval, lazybot does karma and is capable of inline eval, clojurebot lets you use def / defn and has factoids

12:40 maseb: justin_smith: neat, thanks

12:41 justin_smith: little known fact, buddhists tend to intentionally give wrong answers for every right answer they provide in this channel, so that they don't accumulate karma

12:42 maseb: justin_smith: /rimshot

13:05 xemdetia: I like to think they are dating

13:05 TimMc: aw

13:05 H4ns: TimMc: my first goal is to make sure that all libraries that are loaded are at the expected version level. then, i want to be able to add new libraries easily, with a reasonable way to keep the dependency list clean.

13:09 TimMc: H4ns: So your first goal is to make sure that what explicitly appears in :dependencies is accurate?

13:10 H4ns: TimMc: ideally, i would only put into :dependencies what i want to use, and at the versions that i want to use, yes.

13:11 TimMc: so far, what i have learned is that if libraries a and b both depend on c, but with different versions, i need to explicitly depend on c with the version that i would like for both a and b, which blows up my dependency list and moves me away from that ideal state.

13:11 (and which certainly has the potential for disaster if a or b can't work with the newer version of c that i'm now depending on)

13:20 justin_smith: H4ns: at this point, you might save effort if you just constructed your classpath by hand and manually downloaded the artifacts...

13:21 H4ns: justin_smith: that sounds, erm, with all due respect, awful.

13:21 justin_smith: H4ns: but probably simpler than what you are describing

13:23 H4ns: justin_smith: i wonder, am i alone with this? how do you deal with projects that have more than one or two library dependencies?

13:25 justin_smith: H4ns: I try to be selective about deps, and avoid ones with big transitive deps lists. But even if my lein deps :tree shows potential conflicts, I don't stress it unless I see errors

13:25 H4ns: this might be naive, but it also saves me the stress of linearizing everything

13:25 jlegler: And generally, you don't run into many problems unless your project has a huge dependency list.

13:25 It hasn't bitten me yet thankfully.

13:26 sveri: Hi, any thougths on silk vs bidi vs compojure for routing?

13:26 justin_smith: jlegler: in my experience the pain point is when something changes its outward facing api - otherwise I can just use the latest

13:26 hiredman: we have a service at work with around 65 dependencies in its project.clj

13:27 H4ns: hiredman: that is about what we have. do you have :pedantic? :abort in your project.clj?

13:27 hiredman: no

13:27 H4ns: well, maybe that is our problem. :D

13:27 we should probably just ignore that we could be in trouble

13:29 justin_smith: sveri: I don't know silk at all, but to me there is a definite benefit to being able to do reverse routing. I am one of the devs of polaris, which combines reversible routing with declarative edn based route definition (there is a cljx port and I hope to make a cljc version soon)

13:29 hiredman: that list of deps is really stable and some of the clojure libraries are relatively old, for example it is still on slingshot 0.9.0

13:29 bja: sveri, I suppose that depends on what you want to do. I've yet to need to actually reverse urls or want to compose them in any significant way, and thus compojure has been fine for me

13:30 hiredman: so part of the reason it is fine is it never is changed or updated

13:30 justin_smith: bja: my use case for reverse routing is generating relative links in templates - it decomplects the url (which the customer might want changed for aesthetic reasons) from app logic

13:30 H4ns: hiredman: i fear that approach. it pushes the burden to when you need to do the maintenance.

13:30 hiredman: our biggest dependency headaches with it are when we slice part of it out as an independent library dealing with the old deps

13:31 H4ns: I dunno, does it?

13:31 sveri: justin_smith: bja I am looking for a routing library to deliver with closp, compojure has worked so long for me, but I like to have routes as data separated from the service

13:31 H4ns: hiredman: sure, because if you then want to change the software so that it uses the latest version of some dependency, you'll get to update all dependencies, more or less.

13:32 jjttjj: anyone else have the problem where they try to work in another lang after using clojure for a long time and the non-clojure code just seems so ugly it's hard to get into the project

13:32 hiredman: H4ns: well, we very rarely do that

13:33 sveri: justin_smith: using polaris, is there a way to pass down arguments the handler chain? (routes -> route-definitions -> handler)

13:33 hiredman: this is a mature bit of software so we really value stability over bleeding edge

13:34 I newer service has around 40 deps, mostly the same as the old service, some newer versions of the same libraries, etc

13:34 a

13:35 justin_smith: sveri: the route definitions are edn (so they could be a static data structure or get pulled from a db or generated by some code), and yeah, there is a facility for parsing parameters out of the route

13:35 sveri: if I understand your question

13:35 H4ns: hiredman: okay, so from your experience, incompatible pieces of library dependencies do not happen, so :pedantic? :abort is not worth the trouble?

13:35 bja: justin_smith: ah. I don't reverse routes ever, since the link to pieces of content comes in form of UUID (content type, content_type_version, and id) and thus is looked up by caller according to how they resolve content types

13:35 I don't know that I actually have any apis that are large enough to refer to themselves

13:35 just a bunch of tiny ones

13:36 hiredman: I think the only dependency there to deal deps that require different versions of transtive deps was for slingshot

13:36 justin_smith: bja: yeah, this is about generating links on an actual web page in my case

13:36 hiredman: H4ns: I guess, we've never used it

13:36 H4ns: hiredman: thanks!

13:36 bja: yeah. I mean if you're trying to build html links, reversability seems like a must have

13:37 hiredman: H4ns: the old project predates :pedantic?, and by the time the new project kicked off we were set in our ways

13:37 sveri: justin_smith: I think I mean something different, I am currently using the component system so that I can pass a database instance around, this way I can also pass down the db connection to the actual handler. something like that: (defn routes [config] (compojure/routes (GET "/" [] (index-page (:db config))) and then (defin index-page [db]... where index-page is the handler I am talking of

13:38 hiredman: (to get technical the old project predates lein, as I never tire of pointing out)

13:40 I suspect had :pedantic? existed when the project was started it would have been turned on, and who can say what the out come of that would have been

13:40 justin_smith: sveri: oh, yeah, you can float or sink middlewares onto subroutes

13:41 sveri: the extra args are attached to the request map rather than being a separate explicit arg though

13:42 sveri: or maybe it would be more clear to say we provide extra data like a db from a component via a middleware on the route, or a parameterized function that returns the handler, constructed at component start

13:43 TimMc: H4ns: I have the beginnings of a lein plugin that will at least allow you to notice when you've changed a transitive dep unexepectedly.

13:43 That might help you from the other end.

13:45 sveri: justin_smith: I see, as always there are several options, putting them into the request map seems like the "easiest" solution. Is there a chance that polaris gets a cljs port any day soon?

13:45 justin_smith: sveri: cljx exists in a fork by quile, cljc will definitely happen (not sure how soon)

13:45 H4ns: TimMc: if you want to share that, i'll gladly look at it. it might be that i can build on it.

13:47 sveri: justin_smith: ok, thank you very much, as usual, very helpful :-)

13:47 (inc justin_smith)

13:47 lazybot: ⇒ 261

13:50 TimMc: H4ns: There's nothing really there yet, but if you want to follow the project: https://github.com/timmc/lein-diff

13:51 H4ns: TimMc: thanks, watching it now

13:51 hiredman: hehe

13:52 :pedantic? :abort causes lein to npe for me when trying to print out exclusions

13:53 TimMc: H4ns: The first pass will be git-specific and assume that the :depdendencies list is all there is to see, no plugins, etc.

13:53 Later versions will be fancy in whatever direction seems necessary. :-P

15:42 m1dnight_: is it me, or doesnt the ant simulation actually work?

15:42 I mean, after a while, all ants still run around over the entire map

15:47 sveri1: m1dnight_: I guess they got drunk so late at night?

15:49 amalloy: m1dnight_: are they supposed to do something different?

15:54 m1dnight_: well, the intent of the ant simulation is that after N minutes/hours they all walk the same path and that would solve the shortest path problem

15:54 but from whatI can tell they are yeah, drunk :p

15:56 amalloy: is that really what the ant simulation is about? i guess i never actually ran it

15:57 m1dnight_: yep, thats one of the things they use ant simulations for

15:57 http://en.wikipedia.org/wiki/Ant_colony_optimization_algorithms

15:58 justin_smith: m1dnight_: cool - we should make a modified version that includes stilts http://news.nationalgeographic.com/news/2006/06/060629-ants-stilts.html

15:58 amalloy: yeah, reading through it now i see what it's up to

15:59 i always just sorta assumed it was a demonstration that in clojure you could have a zillion threads working on the same data at once without stepping on each other's data or locking

15:59 m1dnight_: yeah thats a nice demonstration of it

15:59 however, if you take too many ants the transaction reach their limit though :>

15:59 transactions*

16:01 stuartsierra: Maybe there's still randomness in the ants' behavior.

16:02 m1dnight_: that's my guess. the ant moves randomly unless it reached home or food

16:02 my guess is that forward/backward should have a tad more priority

16:03 Robert Johnson, an ecologist who studies ants at Arizona State University, considers the finding "cool."

16:03 from that article you linked justin_smith :>>

16:03 justin_smith: haha

16:03 I mean yea, it is cool

16:04 amalloy: i don't think there's any randomness in the ants' behavior aside from the inherent messiness of thread timing

16:04 justin_smith: m1dnight_: though the part about chopping off leg segments reminded me of a terrible manga

16:05 but proof that ants count is awesome

16:05 TimMc: "count"

16:06 justin_smith: TimMc: obviously not in the way we learn to count - probably something closer to the kind of counting musicians learn to do

16:06 TimMc: Just like I count my footsteps like any normal person when walking around in my normal human neighborhood.

16:06 justin_smith: more of an instinctive odometer-like thing

16:06 heh :)

16:06 numberMumbler: i like how they had to be careful when adding the stilts... meanwhile, they are chopping off other ants' legs

16:06 justin_smith: TimMc: a common side effect of musical training is to discover you now count all your steps whether you want to or not

16:07 m1dnight_: how do musicians count then?

16:08 http://en.wikipedia.org/wiki/Counting_%28music%29 <-- like that?

16:08 justin_smith: m1dnight_: it's more of a "feel" - you know how many beats it's been, but you haven't been thinking each number consciously

16:08 m1dnight_: ah thats cool actually

16:09 justin_smith: m1dnight_: what you linked to is more about how that "feel" of the count is taught, not the counting that happens normally. But this is all *way* off topic.

16:10 * m1dnight_ returns to topic

16:10 m1dnight_: Ive just about finished my thesis (actors combined with stm) but my implementation in clojure is.. dirty.

16:10 I hope nobody ever reads it :<

16:10 I had to hack it together in a few days

16:11 justin_smith: m1dnight_: do you have an example problem like the ants?

16:12 m1dnight_: Yeah, im modifying the original ant program to use actors now

16:12 or did you mean, a generic problem that can be solved using ants?

16:12 justin_smith: no, that's what I meant

16:12 m1dnight_: yeah im modifying it.

16:13 But I still dont have transactions across actors, which is what my implementation is all about

16:13 in short: messages are "undone" when a transaction aborts

16:13 but maybe if I make the food piles actors

16:13 TimMc: justin_smith: That's what I was trying to get at -- the ants are probably counting steps the same way we count seconds.

16:14 m1dnight_: working on it now :)

16:14 justin_smith: TimMc: ahh, right

16:14 TimMc: or distance

16:14 Next project: Cut people's legs off at the knees and send them on errands. See if they go the right distance!

16:15 justin_smith: TimMc: 1/3 cut off at knees, 1/3 wearing stilts, 1/3 "unmodified", all blinded to avoid the interference of visual cues

16:15 TimMc: this is terrible, like some kind of GoT version of science

16:32 csd_: Is genclass the only option for exposing Clojure code to Java? Or is there a better alternative?

16:34 justin_smith: csd_: well, a java program can use clojure.lang.RT to access vars (which can then be called via .invoke if they are functions...) so it depends on what the person on the java side is willing to do

16:35 but RT is definitely the most powerful java->clojure

16:35 csd_: would that be substantially faster?

16:35 justin_smith: it's more flexible, less hassle for the clojure side

16:36 I don't know if there would be much meaningful difference perf wise

16:36 csd_: justin_smith: I'm really wondering what kind of interface to expose to Java, just thinking from the perspective of writing the CLJ

16:36 justin_smith: right, but gen-class typically makes things more brittle in my experience

16:36 so my ideal would be to use c.l.RT from java, and just find and invoke the parts of the clojure stuff I want to invoke

16:37 csd_: and all the java has to do is import c.l.RT?

16:38 justin_smith: csd_: yeah, and then resolve and invoke require to get the ns, and resolve and invoke whatever it wants to call

16:38 so there's a few steps, but it gets full access to clj

16:38 csd_: well I imagine the ns would be known in advance

16:39 but sounds easy enough

16:39 justin_smith: csd_: sure, but is it loaded?

16:39 csd_: dont follow?

16:39 justin_smith: csd_: has the clojure compiler loaded and compiled the ns

16:39 that's what require is ensuring

16:39 csd_: ok

16:40 Is there a better discussion of this than http://blog.jayfields.com/2011/12/clojure-java-interop.html ?

16:40 Bronsa: you should use clojure.java.api.Clojure.var rather than clojure.lang.RT.var

16:40 justin_smith: Bronsa: oh!

16:40 Bronsa: I had no idea, what's the difference?

16:40 Bronsa: one is public api the other is not :P

16:41 justin_smith: Bronsa: is this a recent thing?

16:41 Bronsa: 1.6 IIRC

16:41 csd_: ostensibly one is more prone to breaking

16:41 kwladyka: ring and compojure: (def app (wrap-defaults app-routes site-defaults)) - how to add there wrap-params? I want get fields from form. Should i use wrap-params?

16:41 TimMc: One is only in new clj and the other is what everyone uses.

16:41 justin_smith: (inc Bronsa)

16:41 lazybot: ⇒ 112

16:41 justin_smith: thanks

16:41 csd_: Is there a better discussion of this than that jayfields blog post I linked above?

16:43 justin_smith: kwladyka: the simple answer is (def app (wrap-defaults (wrap-params app-routes) site-defaults)), but after a few middlewares I like to convert to (def app (-> app-routes (wrap-params) (wrap-defaults site-defaults))) which is equivalent but easier to change in the future

16:44 kwladyka: mmm i tried that and it didnt work

16:44 justin_smith: kwladyka: the next thing to try is to swap the order (much easier when you use the -> version)

16:44 kwladyka: anyway should i use wrap-params or something like (POST "/my_post_route" {params :params} ...)

16:44 justin_smith: sometimes the middleware only work when nested a specific way

16:44 kwladyka: i triend in both way

16:44 *tried

16:45 maybe i did some mistake during this.....

16:45 justin_smith: kwladyka: what you just showed would require wrap-params as a pre-requisite, otherwise params would always be nil

16:45 kwladyka: oh...

16:45 justin_smith: remember that just reloading your code won't change the middleware, unless you pass #'app to your server

16:45 you may need to restart the http server

16:47 kwladyka: hmm or maybe i have to restart app after that?!

16:47 i am ruining app by lein ring server

16:48 ech still doesnt work

16:48 (wrap-defaults (wrap-params app-routes) site-defaults) <- this not work

16:49 justin_smith: did you try (wrap-params (wrap-defaults app-routes site-defaults)) ?

16:49 this is why -> makes this easier, it would be a question of swapping two lines if you do the reasonable thing and have one middleware on each line

16:49 kwladyka: (wrap-params (wrap-defaults app-routes site-defaults)) <- this doesnt work too...

16:50 i am trying read :params by (ANY "/handler" [] handle-dump)

16:50 justin_smith: kwladyka: what arey ou doing to provide the params from the client?

16:50 kwladyka: i have form with method POST and acotion /handler, i click submit button.

16:51 justin_smith: kwladyka: have you tried passing in the whole request, and then exploring what is actually coming in?

16:53 kwladyka: what do you exatly mean?

16:53 justin_smith: kwladyka: I don't recall how it's done in compojure off the top of my head, but instead of providing the :params, you can provide the whole request object

16:54 csd_: justin_smith: would a project.clj be necessary for Java integration?

16:54 justin_smith: ring takes a request from a client and turns it into a hash map, and that's what all the middleware use/modify, and then the final form is used to derive the data to pass to your handler

16:54 kwladyka: in :params i have only :__anti-forgery-token so it works, but i don't have other fields

16:55 justin_smith: csd_: it would help, my plan of action would likely be to create an uberjar that would become a part of whatever java thing, and the project.clj could help with that

16:55 but another option would be to use maven directly (or whatever else) to resolve all the clojure deps

16:55 csd_: I think we'd go the maven route, most likely

16:56 justin_smith: csd_: yeah, if you are using maven directly, no need for project.clj, you can just make a pom.xml for your clojure code

16:56 kwladyka: justin_smith, BTW do you use ring + compoure or something more complex?

16:56 justin_smith: since java would be in the driver's seat

16:57 kwladyka: something less complex, compojure is weird imho :P

16:57 csd_: ok thx

16:57 justin_smith: I usually use ring+polaris, but bidi is also good

16:57 kwladyka: justin_smith, less? only ring?

16:58 i was thinking about bidi to learn that in next step

17:03 oh no.... no ;( i have misspell in HTML ;(

17:03 no... hours of my time ;(

17:09 thank you as always

17:09 ok its time to sleep, goodnight :)

17:27 ghadishayban: /msg bronsa (invoke-dynamic* "name"

17:27 clojure.lang.Bootstrap/protocol-invoke

17:27 method-type ;; [retclass argclasses..]

17:27 ... static args)

20:41 criosphinx: lmfao!!!!!!!!! https://www.youtube.com/watch?v=XR_GkTLg

20:41 lmfao!!!!!!!!! https://www.youtube.com/watch?v=XR_GkTLg

20:41 lmfao!!!!!!!!! https://www.youtube.com/watch?v=XR_GkTLg

21:58 binjured: what's an idiomatic way to do something like `(while (next foo) (:bar foo))' that collects results?

21:58 amalloy: map

22:00 binjured: does that work for random Java objects that use a `next() bool` method?

22:00 weavejester: binjured: If they implement an iterator, you can use iterator-seq to convert them to a seqence.

22:00 But normally it just works with seq-able objects.

22:01 So Clojure collections, and some basic Java types.

22:03 binjured: weavejester: this object doesn't implement anything, just happens to use the next() idiom

22:03 amalloy: in fairness, a lot of java types

22:03 binjured: that is a remarkably hostile object. are you sure?

22:04 weavejester: Yeah, most Java collections as well, tbh

22:04 binjured: You can use iterate to convert it to a seq I believe

22:04 binjured: amalloy: unless i forgot how to read api docs, which is totally possible: http://download.eclipse.org/jgit/docs/jgit-2.0.0.201206130900-r/apidocs/org/eclipse/jgit/treewalk/TreeWalk.html

22:04 amalloy: weavejester: only if it actually implements iterator

22:04 weavejester: amalloy: No, not iterator-seq, iterate.

22:05 (iterate #(.next %) blah)

22:05 Unless .next is side-effectful

22:05 amalloy: weavejester: it is

22:05 and returns bool

22:05 weavejester: Ah, right

22:05 binjured: weavejester: yeah, it is. next() basically just moves an internal pointer and returns true if it wasn't at the end.

22:06 amalloy: this jgit api is pretty awful

22:06 weavejester: There's another function I believe that deals with side-effectful sequences

22:06 amalloy: is there? i don't think there's anything smarter than iterate

22:07 weavejester: Oh, right, repeatedly. Duh me.

22:07 amalloy: i think the only thing you can do while still being correct is loop/recur, or a custom recursive function returning lazy-seq if you're returning a sequence

22:07 binjured: all i've thought of is use loop/recur and transient to save some effort.

22:07 weavejester: Oh, except that still wouldn't work.

22:07 Okay, clearly my brain is too tired to think.

22:08 amalloy: weavejester: i mean, (repeatedly #(doto % .next) thingy) will generally work in practice

22:08 but it's not guaranteed to work

22:08 weavejester: Yeah, I realised that when I said it :)

22:09 binjured: amalloy: i'd prefer it were lazy, but i'm not clear on how to do that with the loop.

22:09 amalloy: binjured: are you returning something lazy?

22:09 sdegutis: Just use ->>

22:09 amalloy: that is, is your return type amenable to laziness (is it a seq)

22:10 binjured: amalloy: my return type is whatever i want it to be, so yea ;) ... using loop/recur and conj it would just be a vector.

22:10 amalloy: okay. so you instead want (defn make-foos [thingy] (lazy-seq (when (.next thingy) (cons (.getwhatever thingy) (make-foos thingy)))))

22:11 weavejester: (defn f [x] (lazy-seq (cons (bar x) (f (doto x .next))))

22:11 sdegutis: Just use a lazy seq.

22:11 weavejester: amalloy's version is better :)

22:11 I think it's time for me to go to sleep.

22:11 amalloy: mostly because it actually stops when thingy runs out of nexts

22:11 binjured: haha

22:11 that is a plus...

22:12 thanks, amalloy.

22:12 sdegutis: Clojure is so funn!!!!

22:12 Let's get excited!

22:13 binjured: is doall clojure's progn?

22:14 oh, maybe it's just `do`

22:14 amalloy: binjured: it doesn't really exist in CL, because CL doesn't have lazy seqs

22:14 doall doesn't, rather. do is progn

22:27 binjured: amalloy: `(tree-paths (new-tree-walk repo (first (rev-list repo))))' much nicer than the jgit api ;)

Logging service provided by n01se.net