#clojure log - Jan 28 2015

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

0:09 Jabberz: there a good way to mock core.async in tests (say midje tests), so you don't have to create a bunch of channels and the like, but verify say something got put onto a mock channel?

0:10 tomjack: ah, I see https://www.refheap.com/1e30c198d528300fcba9ef24a

0:10 reification is exponential in depth?

0:11 TEttinger: Jabberz: ##(str "Your mother was a hamster and your father smelt of elderberries, " "core.async")

0:11 lazybot: ⇒ "Your mother was a hamster and your father smelt of elderberries, core.async"

0:11 TEttinger: ...I have never used midje or core.async

0:15 tomjack: Jabberz: would a mock channel behave differently from a normal channel?

0:16 Jabberz: tomjack: it would be nice to say something like (some-fun) => (>! some-data) in a test, rather than go through the whole ceremony of setting up the plumbing

0:18 afaict, you can't do a (provided (>! ...) in midje, because it's not a function, it's the from-hell-macro, so that's kinda leaving me at setting up the channels unless someone's already solved this type of problem elsewhere and wrapped it in a nice little library? :D

0:20 tomjack: and yeah, I don't want to deal with lots of async stuff running all over the place in the tests, and having to wait, or join or latch on, so that's kind of the motivation -- stub out the core.async, and just verify that the business logic that puts stuff on/takes stuff out of the queues is all correct

0:21 tomjack: you want to check that some-data was put into _any_ channel?

0:22 otherwise, you're going to have to pass something (a mock channel?) in? at that point I fail to imagine how the mock channel would behave differently from a normal channel

0:22 Jabberz: in midje terms, just that channel put was called with some args

0:23 tomjack: you can check put! I think then

0:24 Jabberz: I'm basically treating core.async similar to a db -- wanting to mock out the interactions with it, so all the business logic gets unit tested, and the pick up exercising the async and db stuff all together in end-to-end functional tests

0:26 tomjack: ok, just check for clojure.core.async/put! ?

0:26 dunno, good luck :)

1:01 catern: http://blog.venanti.us/ultra/

1:02 >About two months ago I decided I'd been writing Clojure long enough that the time had come to optimize my development environment.

1:02 web devs should be banned :(

1:02 from everything

1:02 hipsteerrrrrrs

1:02 (that is all)

1:04 sharkz: Hi, how can I create a list '((10 20) (11 21)) from '(10 11) and '(20 21)

1:05 I want to create a one-by-one pair of two equally-sized lists

1:05 slipset: ,(list '(10 11) '(20 22))

1:05 clojurebot: ((10 11) (20 22))

1:06 slipset: ,(map list '(1 2) '(2 3))

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

1:07 sharkz: that's is cool

1:07 *that's cool

1:07 slipset: :)

1:08 sharkz: I didn't know map can iterate multiple lists

1:08 thank you so much :)

1:08 slipset: No problem!

1:08 profil: sharkz: map can: "(map f c1 c2 c3 & colls)"

1:09 slipset: ~map

1:09 clojurebot: map is *LAZY*

1:37 Kneiva_: ,(mapv list '(10 11) '(20 21))

1:37 clojurebot: [(10 20) (11 21)]

1:37 Kneiva_: sharkz: isn't this what you wanted? --^

1:41 teajoe: Hey guys! So I'm reading about macros @ Brave & True, and I stumble upon the postfix macro: evaluates a function defined in postfix notation. This is pretty cool, but can I do it for any entire application (evaluate the entire app as postfix)? I've heard lisps are very oriented to tweaking themselves, but am still new to this. danka

2:38 clj123: how can I merge all seq within seq. For eg [[1 2 3] [4 5 6] [7 8]] => [1 2 3 4 5 6 7 8]

2:40 TEttinger: clj123: ##(apply into [] [[1 2 3] [4 5 6] [7 8]])

2:40 lazybot: clojure.lang.ArityException: Wrong number of args (4) passed to: core/into

2:40 TEttinger: clj123: ##(into [] [[1 2 3] [4 5 6] [7 8]])

2:40 lazybot: ⇒ [[1 2 3] [4 5 6] [7 8]]

2:40 TEttinger: dammit I can't remember

2:40 havenwood: ,(vec (flatten [[1 2 3] [4 5 6] [7 8]]))

2:40 clojurebot: [1 2 3 4 5 ...]

2:40 ucb: ,(apply concat [[1 2 3] [4 5 6] [7 8]])

2:40 clojurebot: (1 2 3 4 5 ...)

2:40 TEttinger: &(apply concat [[1 2 3] [4 5 6] [7 8]]) is correct, flatten is...

2:40 lazybot: ⇒ (1 2 3 4 5 6 7 8)

2:41 TEttinger: ~flatten

2:41 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

2:41 havenwood: interesting

2:41 TEttinger: thanks, good to know!

2:41 TEttinger: havenwood, I use flatten all the time, but only when I have total control of the data I am using

2:41 usually only for things I know are small and shallow

2:42 clj123: cool thanks

3:20 muhuk: Hi all.

3:20 SagiCZ1: morning..

3:25 hellofunk: zacts: those books look interesting, i'll check them out

3:33 ianhedoesit: SagiCZ1: it's 00:31!

3:33 SagiCZ1: ianhedoesit: ever heard of time zones?

3:33 ianhedoesit: no!

3:33 SagiCZ1: reminds me of some of my american friends

3:33 ianhedoesit: I live in a world where I reject the notion of timezones.

3:34 hellofunk: ianhedoesit: and yet, you make a big deal out of the time

3:34 SagiCZ1: ianhedoesit: at least you don't deal with jet lags!

3:34 hellofunk: :0

3:34 ianhedoesit: I figure date time messes are too messy in the first place, even if I ignore timezones.

3:35 and my data is never more than a day off, so it's not really an issue.

3:35 SagiCZ1: ianhedoesit: i am fascinated by half our or quarter hour timezones.. that must really weird

3:35 *hour

3:36 ianhedoesit: SagiCZ1: I've never understood those. I haven't looked into why any place has those sorts of time zone variations though.

3:36 SagiCZ1: ianhedoesit: i think it's places that literally don't have any other interesting thing..

3:37 daniel`: sud afrika

3:37 ianhedoesit: http://www.timeanddate.com/time/time-zones-interesting.html

3:38 SagiCZ1: i hope joda time knows about all these

3:38 ianhedoesit: the first thing it talks about is India and why it has a 30 minute offset from UTC. actually kinda interesting.

3:40 neat, only two places in the world have quarter hour offsets!

3:40 how informative to the clojure community!

3:42 hyPiRion: SagiCZ1: yup, it does

3:42 SagiCZ1: hyPiRion: cool

3:51 Glenjamin: the UK is the worst: if you forget to handle timezones your software still works 50% of the year

3:52 hyPiRion: If you forget to handle time, it'll still work twice a day. etc

3:53 Glenjamin: do people have this problem in other timezones? I've only ever worked in GMT

3:54 9/10 callsites convert to UTC - software only broken from march-october.

3:55 hyPiRion: There is DST many places on earth

3:55 Glenjamin: right, but the non-dst zone isn't === UTC ?

3:56 so if you're storing UTC, you'd notice if you miss one

3:56 hyPiRion: oh, sure thing. Ish

3:56 wink: Glenjamin: we're one off with CET - so glancing at logs it can be mistaken for UTC easily

3:56 hyPiRion: are you goin to FOSDEM?

3:57 clgv: Glenjamin: I like the time zones with offsets of additional 30min or 45min

3:57 wink: I found http://qntm.org/abolish an interesting read

3:58 hyPiRion: wink: nope, unfortunately

3:58 Glenjamin: clgv: i would imagine anyone working in those zones gets good at time quite quickly

3:58 certainly people working in those zones communicating times to people in other zones

4:14 SagiCZ1: Glenjamin: i dont think people in those timezones communicate with the outside world that much

4:15 ianhedoesit: yeah, Nepal and New Zealand are pretty lonely.

4:44 clgv: SagiCZ1: australia? :P

4:44 SagiCZ1: clgv: they dont have full hour timezones?

4:44 clgv: SagiCZ1: check Darwin

4:44 SagiCZ1: clgv: oh nevermind then.. that's embarassing.. sorry :X

4:45 clgv: SagiCZ1: the other exotic ones are in southern asia

4:46 I'd never guessed that there are time zones with offset +13/+14

4:46 cfleming: Here in New Zealand we use a full hour offset, but we're still pretty lonely down here.

4:47 Empperi: cfleming: sorry saying this from here, not from official channels but latest Cursive update broke debugging both in Mac and Windows

4:48 SagiCZ1: cfleming: do you kiwis get to visit Australia often? they seem pretty close but I imagine some people may never leave the island..

4:48 Empperi: Idea 14

4:48 cfleming: Empperi: Do you mean 0.1.44? 0.1.43 broke it, 0.1.44 should have fixed it

4:48 Empperi: dunno, just the update Idea automatically told me to update :)

4:48 cfleming: SagiCZ1: Sure, Kiwis travel a lot

4:49 Empperi: but good to know

4:49 SagiCZ1: cfleming: cool//

4:49 Empperi: will check that I have the latest version

4:49 missing my debugger... :P

4:49 cfleming: Empperi: If you have 0.1.44 and it's broken let me know. It should be much better in 44 than 43 - more reliable breakpoints and expression eval now finally works, so breakpoints can have conditions etc

4:50 Empperi: I haven't forgotten about your action issue either BTW, just busy, sorry

4:50 SagiCZ1: cfleming: btw, i am struggling to understand how REPL history works.. for example when i work in REPL, then close it and open a new one, i dont have the latest history from the just closed REPL but some arbitrary history from the past.. i also tried to check the "Show history" window, and that was somewhat confusing as well

4:50 Empperi: cfleming: actually, I might have an idea what is causing it and it is not Cursive related

4:50 it's about how Idea reads the keybindings

4:51 for example, I have "load namespace into REPL" in keybinding ctrl+alt+l

4:51 if I happen to press alt down before ctrl, or if I press them at the same time then it doesn't work

4:51 cfleming: SagiCZ1: That sounds weird, it should have a relatively straightforward linear history

4:51 Empperi: if I press ctrl down first, then alt and then l, then it works

4:51 SagiCZ1: cfleming: even when working across multiple REPLs? how should that work?

4:51 Empperi: annoying but should point to the fact, that the problem is *not* in Cursive

4:52 and this problem is not there with Mac

4:53 cfleming: Empperi: That sounds really weird - you're on Windows, right? Does this happen on a Mac too?

4:53 Empperi: Oh, no, ok

4:53 Empperi: I use both and this happens only on Windows

4:53 TEttinger: Empperi: try also binding alt-ctrl-l

4:53 if it distinguishes between ctrl-alt and alt-ctrl, maybe it's configurable

4:53 Empperi: will do when I'm on pc again, right now doing work at home with my work laptop (mbp)

4:54 TEttinger: still the strangest IDE quirk I've heard of in a while

4:54 Empperi: yeah

4:54 anyway I can live with that now that I know what is causing the problem

4:55 I was getting sick and tired of going to menu just to load the file into repl...

4:56 cfleming: Empperi: Yeah, I bet. That sounds like a JDK issue to me.

4:56 Empperi: cfleming: that doesn't happen on any other software, just with Idea

4:57 cfleming: SagiCZ1: The REPL history is partitioned by type, so local REPLs have a separate history from remote ones.

4:57 Empperi: and my keybindings for Cursive happened to bring it up

4:57 cfleming: SagiCZ1: But within a particular type, it should do what makes sense - I'd have to check the code to remind myself exactly when it syncs what to the history

4:58 SagiCZ1: But if you do "Show REPL history" it should show your recent history from the current REPL, definitely

4:59 SagiCZ1: BTW the closest point in Australia is still 3.5 hours on a plane from here, it's like Paris to Tel Aviv maybe - still a long way

4:59 engblom: I just solved Martin Gardners coconut problem. I wonder if this is how everybody would solve it or if there is a better clojure solution. The problem and my solution is here: http://pastebin.com/0axr8rZW

5:22 TMA: engblom: it is an excercise for chinese remainder theorem and modular arithmetics -- you are not supposed to brute force the solution

5:25 clgv: engblom: as TMA says ;)

5:26 engblom: when you don't know about CRT you could at least restrict the search space by reasoning about divisibility of the numbers ;)

5:27 tomjack: (I'm 80% certain that) my problem was a perf bug in core.logic! :)

5:36 I believe it had been there since 2012 and would, I think, have caused a significant penalty upon getting answers out whenever the answers were relatively deep (perhaps less deep if also wide?) trees

5:39 which is somewhat troublesome, because even in Agda I believe the state of the art for programs whose types verify their complexity is "semi-formal" :(

5:48 Glenjamin: anyone know why the "j" is clojure is italicised?

5:48 engblom: TMA: This was neither a school task or any excersise I would be forced to solve. I just coded this one so I can show the benefit of knowing a bit of programming as you can by programming solve (brute force) problems you would not be able without plenty of skills otherwise.

5:49 What I wanted to know if the coding style for brute forcing this problem is good, not how to solve it mathematically.

5:50 I have the mathematical solution. This brute force solution I created is from the point that you should not need more maths knowledge than what elementary school gives.

6:00 TMA: Glenjamin: my take on that: 'tis some kind of reference to Java or JVM

6:02 lachenmayer: Glenjamin: to emphasise that clojure is not closure or clozure? ;)

6:03 TMA: engblom: as for the coding style [disclaimer: I come from common-lisp/scheme background] ... I would personally split the printing and computation into separate functions

6:06 Glenjamin: always good advice imo ^

6:07 engblom: But you would use list comprehension for brute forcing?

6:27 clgv: engblom: but the problem can be easily scaled such that the brute force attempt fails ;)

6:33 TMA: engblom: yes. having the data fed to the bruteforcer as a lazy sequence [or a generator function in vanilla CL] seems like a good concern separation

6:33 engblom: also: no space before ) :)

6:40 engblom: (defn compute-solution [candidates] (for [i candidates ...] ...))

6:42 engblom: TMA: So you generate a list of canditates and then feed it to compute-solution?

6:43 TMA: engblom: not a list -- a lazy seq

6:44 engblom: (range) ?

6:44 TMA: engblom: in Common Lisp... (defun compute-solution (candidate-fn) (do ((i (candidate-fn) (candidate-fn)) ...) ...))

6:45 engblom: range produces a lazy seq, not list

6:45 engblom: in other words: yes

7:00 H4ns: justin_smith: as sad as it may be, i've decided to use imagemagick because me.raynes.conch is awesome and the java image libraries are not.

7:04 TEttinger: imagemagick is awesome though

7:04 H4ns: TEttinger: much awesomer than the java image stuff

7:06 TEttinger: here, try saving a file as pbm, with options -compress none -depth 8. remove the first two lines of the pbm's text output. stick a [ and a ] on the ends and now you have a valid clojure vector that you can parse with read-string

7:06 if there are less than 11 colors, at least

7:06 which for PBM should be always

7:08 arossouw: are there clojure forums, where i can ask skilled clojure coders to criticize my code?

7:08 TEttinger: arossouw: link to refheap or gist with your code and people will try here

7:08 arossouw: i see, thanks

7:08 TEttinger: there probably are forums

7:09 Glenjamin: there's codereview on stackexchange

7:09 arossouw: cool, thanks

7:09 TEttinger: (inc Glenjamin)

7:09 lazybot: ⇒ 11

7:10 arossouw: i've tried something like this, not sure how to access outer block (#(take %1 %2) 3) '(1 2 3 4))

7:11 justin_smith: arossouw: there is a misplaced paren in there somewhere

7:11 what is that trying to do?

7:12 &(#(take %1 %2) 3 '(1 2 3 4))

7:12 lazybot: ⇒ (1 2 3)

7:12 Kneiva: ,((partial take 3) '(1 2 3 4))

7:12 clojurebot: (1 2 3)

7:12 arossouw: lets say, x is argument 1 for amount of elements to drop y is argument 2, should do ((take x y) 3) '(1 2 3 4))

7:12 justin_smith: arossouw: again, you have an extra paren

7:12 arossouw: i see

7:12 justin_smith: that doesn't even make sense

7:13 arossouw: ok, i'll play around abit

7:13 TEttinger: (doc split)

7:13 clojurebot: Huh?

7:13 TEttinger: (doc split-at)

7:13 clojurebot: "([n coll]); Returns a vector of [(take n coll) (drop n coll)]"

7:13 arossouw: (= (__ 3) '(1 1 2))

7:13 4clojure, dont want answer just hint

7:13 where __ is function

7:14 TEttinger: fibs

7:14 justin_smith: oh yeah, that's definitely fibs

7:15 arossouw: so i should create an anonymous function that generates fibs and only print first 3?

7:16 justin_smith: not print, return

7:16 arossouw: ah, ok, thanks

7:16 justin_smith: arossouw: you need a function that takes a number n, and returns the first n fibs

7:19 zacts: helgikrs: http://mitpress.mit.edu/books/cognition-basic-musical-structures

7:25 TEttinger: from clojuredocs: ,((fn [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1))) 3)

7:25 ,((fn [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1))) 3)

7:25 clojurebot: (1 1 2)

7:25 arossouw: cool

7:25 i'll have to study lazy-seq, still new at that

7:25 TEttinger: see for yourself how to do it http://clojuredocs.org/clojure.core/lazy-seq

7:25 it's very powerful

7:26 ,(defn fibonacci [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1)))

7:26 clojurebot: #'sandbox/fibonacci

7:26 TEttinger: ,(fibonacci 30)

7:26 clojurebot: (1 1 2 3 5 ...)

7:26 Glenjamin: i completely failed to write a function using lazy-seq in an interview this week :(

7:26 TEttinger: ,(clojure.string/join " " (fibonacci 30))

7:27 clojurebot: "1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229 832040"

7:27 TEttinger: Glenjamin, yeah I would have too

7:27 arossouw: it would crash if you did it recursively right? (with python)

7:27 Glenjamin: i managed to write the loop..recur

7:27 zacts: hellofunk: http://mitpress.mit.edu/books/ant-colony-optimization <- cool my next clojure project is going to utilize ideas from this

7:28 Glenjamin: but then didn't look at the docs enough to write the lazy-seq, and got a bit tied up :(

7:28 TEttinger: arossouw, lazyseqs are often infinite. you only evaluate a finite portion by using take

7:28 zacts: helgikrs: sorry man, I meant that for hellofunk

7:28 arossouw: awesome

7:28 justin_smith: arossouw: yeah, if it were evaluated eagerly it would go into a loop until it ran out of stack space

7:28 arossouw: i think data scientists would love that

7:28 justin_smith: arossouw: what lazy-seq does is it creates something that acts like a list, but to get the next item you need to call a function

7:29 arossouw: and python does have something like that, it just has a more confusing way of using it

7:29 arossouw: so it releases memory on each iteration?

7:29 TEttinger: it keeps it around.

7:30 however java will garbage collect unused stuff

7:30 justin_smith: it actually uses more memory each iteration (but it can be released if you don't hold onto the beginning of the series)

7:30 arossouw: interesting

7:31 it would be cool if you could download a pdf of clojuredocs.org

7:31 justin_smith: like if you have (def r (range)) and then (nth r 1000000000) you'll use a huge amount of memory, but if you just have (nth (range 1000000000)) that won't

7:31 err (nth (range) 1000000000) that is

7:32 arossouw: ok, nth vs get ,which to choose?

7:32 justin_smith: get is for associative things

7:32 nth is for things that are ordered

7:32 vectors are both

7:32 arossouw: ah

7:32 justin_smith: but otherwise the choice is clear, because only one of the two makes sense

7:33 if a coll supports both get and nth, they are likely identical

7:34 (for that coll)

7:34 also ##(nth [1 2] 22 :not-there)

7:34 lazybot: ⇒ :not-there

7:34 justin_smith: nth takes an optional "not found" arg, like get does

7:35 arossouw: oh

7:38 i think this might be a bit inefficient, https://gist.github.com/arossouw/2adb82ad208295be31a2

7:40 justin_smith: arossouw: one small thing - (complement nil?) is the same as some?

7:40 arossouw: possibly, i'll try

7:40 justin_smith: they are identical

7:40 arossouw: oh

7:40 ok

7:40 thanks

7:40 justin_smith: I mean some? is the name of the function, the question mark is part of the name :)

7:41 arossouw: yeah, get it, seen that function

7:41 justin_smith: and (keep f coll) is the same as (filter some? (map f coll))

7:41 TEttinger: (remove nil? collection)

7:41 * arossouw taking notes

7:41 justin_smith: so you can just return (keep #(last (re-find re-imap-login %)) line)

7:41 and skip two let bindings

7:42 arossouw: nice

7:42 justin_smith: that makes things more clear, but doesn't change the efficiency

7:42 TEttinger: err, one let binding justin_smith

7:43 justin_smith: TEttinger: it eliminates two, because the second is just the return value now :)

7:43 TEttinger: the line with filter is outside the bindings

7:43 justin_smith: arossouw: also, (apply str (map (fn [x] str x "\n")) ...) could just be (clojure.string/join "\n" ...)

7:44 arossouw: awesome

7:44 justin_smith: TEttinger: yes, and I am replacing it with keep

7:44 TEttinger: oh, now I get it, never mind :)

7:44 you are right

7:44 TEttinger: heehee

7:44 justin_smith: I was confused momentarily by the indentation

7:44 TEttinger: (inc justin_smith)

7:44 lazybot: ⇒ 173

7:44 TEttinger: (inc indentation)

7:44 lazybot: ⇒ 1

7:45 justin_smith: arossouw: in that case, the string/join will be faster than apply / str / map combo

7:46 since you don't need to create the temporary lazy seq before making the string

7:49 arossouw: justin_smith: how would i apply join "\n" to line-seq (io/reader file)?

7:49 justin_smith: ,(clojure.string/join "," [1 2 3])

7:49 clojurebot: "1,2,3"

7:49 arossouw: ah

7:49 justin_smith: just make the line-seq the last arg to the join

7:52 slipset: ,(apply str (interpose \, [1 2 3]))

7:52 clojurebot: "1,2,3"

7:52 justin_smith: slipset: that has the correct output, but string/join is always better

7:53 slipset: most probably true, but I'm somewhat fond of interpose :)

7:54 TEttinger: interpose and interleave are both quite useful

7:55 justin_smith: (defn interject [e coll] (let [position (rand-int (count coll))] (concat (take position coll) [e] (drop position coll)))

7:55 slipset: besides, this is kind of cool

7:55 (apply str (interpose \, "123"))

7:56 ,(apply str (interpose \, "123"))

7:56 clojurebot: "1,2,3"

7:56 justin_smith: ,(clojure.string/join \, "123")

7:56 clojurebot: "1,2,3"

7:56 arossouw: https://gist.github.com/arossouw/2adb82ad208295be31a2 , looks slightly better now, thanks for the help

7:56 slipset: (inc justin_smith)

7:56 lazybot: ⇒ 174

7:56 slipset: didn't know about that one :)

7:57 justin_smith: arossouw: don't forget you need (require '[clojure.string :refer [join]]) for that to work

7:57 or my preference, (require '[clojure.string :as string]) and change join to string/join

7:57 arossouw: ok

7:57 justin_smith: also, that map needs to be keep

7:58 otherwise you still get nils

7:58 arossouw: oh, cool, thought you ment like keep, like keep that part

7:59 see now, great stuff

7:59 justin_smith: ,(keep next [[1] [12 13] [42] [5 7 9 11]])

7:59 clojurebot: ((13) (7 9 11))

8:00 arossouw: so much to learn

8:00 justin_smith: if I had named keep, I likely would have called it winnow

8:00 arossouw: refactored now :-) https://gist.github.com/arossouw/2adb82ad208295be31a2

8:00 justin_smith: (getting rid of the husks :))

8:02 arossouw: anyone here using http-kit with nginx in production?

8:02 justin_smith: yes

8:02 not via the plugin though

8:02 arossouw: do you have to lein uberjar everytime you submit your code?

8:02 justin_smith: yes

8:02 arossouw: justin_smith: do you use midje to test the stuff or deftest?

8:03 justin_smith: clojure.test (deftest)

8:03 arossouw: ok

8:03 hows the performance sofar?

8:03 justin_smith: it's been excellent

8:03 arossouw: of nginx + httpkit

8:03 justin_smith: haven't had to scale beyond one server yet

8:03 arossouw: interesting

8:04 planning on rewriting python web app to http-kit + compojure + nginx

8:04 justin_smith: cool

8:04 arossouw: don't like orm's for some reason

8:04 justin_smith: that's a smart thing to dislike

8:04 arossouw: lol

8:05 is clojure gaining market share?

8:06 justin_smith: I think so, yes

8:06 though being a lisp, I don't know how big a market share it can reach

8:07 arossouw: does lisp have a bad reputation?

8:07 justin_smith: it doesn't look like math the way you learn it in highschool

8:07 tbaldridge: arossouw: no, it just requires you to think a bit more before you start to code

8:07 justin_smith: people are reluctant to learn the syntax

8:08 tbaldridge: arossouw: with great power comes great responsibility

8:08 arossouw: i see, its unfamiliour to most and people usually prefer to stick to known stuff

8:08 i'm afraid i can't like any other programming language now

8:09 justin_smith: yeah, it's a simple language barrier issue, and most people are not motivated enough to get past the small amount of learning needed for prefix notation (especially with mathematical stuff)

8:09 hehe

8:10 after you gain some competency, try something in the ml family too - syntactically very different, and strong typing is a different reality, but they share many of clojure's positive qualities

8:10 arossouw: do you think it might persaude people if you give a clear overview of the benefits of functional coding?

8:10 justin_smith: (OCaml, sml, haskell maybe)

8:10 arossouw: perhaps, I think the main thing that will convince people is if we show them great things we can make (and how easy it is to make more like that)

8:10 arossouw: tried haskell, will try again, tricky to learn

8:11 justin_smith: yeah, haskell is a challenging language

8:11 but it's worth knowing at least one ml and at least one lisp, imho

8:11 arossouw: ok

8:12 justin_smith: but yeah, I think one thing at a time, and the best way to convince anything is cool is to make something awesome

8:12 arossouw: text parsing is slow in haskell, but i guess i'd need more experience

8:12 justin_smith: haskell has multiple string types, and the default string type is very inefficient

8:13 arossouw: ok

8:13 tbaldridge: and if you want to learn a good ml (not a bad idea) stick with F#. It's like Clojure, but based on ML (instead of Lisp)

8:13 muhuk: if you're interested in haskell but don't want to leave JVM world; try frege

8:13 justin_smith: tbaldridge: yeah, F# is a good one (it's heavily derived from OCaml, my favorite ml)

8:14 tbaldridge: I started playing with ML awhile back, but was put off by how bad the library support was. That's mostly fixed by F#

8:14 luxbock: tbaldridge: when's your next video coming out? I haven't seen any new ones in a while

8:15 arossouw: muhuk: i'll check it out, thanks

8:15 tbaldridge: luxbock: today or tomorrow, I've hit a bit of a writer's block, going to get back into it

8:15 luxbock: tbaldridge: cool. I really like your transducer ones

8:29 dysfun: what's the clojurescript idiom for when you need to initialise a component through a browser API that takes a function?

8:29 e.g. getUserMedia(function() {})

8:30 Glenjamin: pass it a fn

8:30 dysfun: currently i've got it putting onto a core.async channel

8:30 Glenjamin: oh right, i see what you mean

8:30 dysfun: i'm trying to get it *out* of callback mess :)

8:31 i'm using it with om

8:36 Glenjamin: you could probably wrap up the idiom into a channel that's immediately dereffed?

8:38 dysfun: yeah, it's looking like that's the way

8:39 doesn't seem the cleanest, but it has the benefit of being straightforward

8:39 clgv: "wrap up the idiom"?

8:41 dysfun: yeah, once i've got it working, i'll see how to tidy it up

8:53 arossouw: is it possible to create a popup calandar with clojurescript?

8:53 R0B_ROD: arossouw: Its possible to do many things with clojurescript

8:53 arossouw: oh, ok

8:54 R0B_ROD: arossouw: If you layout your problem definition and design a simple algorithm Im sure you will be able to code what you want.

8:54 arossouw: i see

8:55 R0B_ROD: arossouw: I say it as theory since I have no experience with coljurescript or clojure.

8:55 + I mistype all the time

8:56 justin_smith: arossouw: clojurescript has full access to javascript

8:56 clgv: arossouw: you can narrow it down to "is X possible with JavaScript & HTML?"

8:57 justin_smith: arossouw: so you can use whatever javascript libraries are apropriate (and there are calender libs for javascript)

8:57 michaelr525: hi

9:00 arossouw: ok, thanks

9:02 michaelr525: hmm

9:02 Glenjamin: clgv: i should really have said "define a function"

9:02 michaelr525: I need to do this in Clojure: new GenericType<ChunkedInput<String>>() {}

9:02 any idea?

9:03 it's from here: https://jersey.java.net/documentation/latest/async.html#d0e10298

9:03 justin_smith: michaelr525: generics don't exist in the jvm

9:03 they only exist in the java compiler, which we are not using

9:03 ignore the generic part, and just make a ChunkedInput

9:03 michaelr525: justin_smith: I'm not sure it's going to work in this case..

9:04 hyPiRion: justin_smith: GenericType, rather.

9:04 justin_smith: hyPiRion: oh, right, thanks :)

9:04 michaelr525: justin_smith: that code expects to have that type information in runtime..

9:04 hyPiRion: but this is some anonymous class magic instantiation

9:04 justin_smith: michaelr525: generics are not enforced by the vm, in fact they don't even exist

9:04 hyPiRion: so that calls for reify, right?

9:05 hyPiRion: justin_smith: right

9:05 michaelr525: err..

9:05 from the above url: "The entity is read as a ChunkedInput entity. In order to do that the GenericEntity<T> is used to preserve a generic information at run time. If you would not use GenericEntity<T>, Java language generic type erasure would cause that the generic information would get lost at compile time and an exception would be thrown at run time complaining about the missing chunk type definition."

9:06 that's why I don't think it would work ;)

9:08 justin_smith: michaelr525: what that means is that an instance of GenericType is provided as an argument to redEntity

9:08 as hyPiRion said, use reify to create that instance as the first arg to readEntity

9:08 GenericType is what is important here, the generics are just noise

9:10 reify (and sometimes proxy) are how we create anonymous class instances like in that code snippet

9:10 zacts: hi clojurists

9:11 R0B_ROD: Hello justin_smith

9:11 justin_smith: hello

9:11 michaelr525: justin_smith: ok, thanks.. i'll give it a try before wraping that in a java class..

9:12 i'd have to override some of GenerType's methods to return the parametrized type name at runtime

9:12 justin_smith: michaelr525: yes, reify is capable of doing that

9:13 zacts: I feel like my designs in clojure are lacking

9:13 I want to gain more experience

9:13 with functional programming

9:13 justin_smith: zacts: you should make something

9:14 zacts: what to make? :-)

9:14 TMA: zacts: almost anything, really

9:14 zacts: I feel like I know how the pieces move in chess, but don't know how to play the game

9:14 well

9:15 slipset: zacts: if you have a working webapp, implement either the front-end or the back-end in clojure(script)

9:15 If you work in a company which uses irc/slack/hipchat or something, implement a simple bot which looks up jira issues for you

9:16 justin_smith: or, in fact, you could even make a chess engine (save the AI part for later, just do something that can accept valid moves, and reject invalid ones)

9:16 zacts: hum.. nah I don't want to do chess right now

9:16 it was a metaphor for my clojure understanding

9:16 I guess I may just start with the music ideas

9:16 TMA: zacts: I have found that at least for me the main point was to change the thinking. the designs then came spontaneously

9:17 zacts: I like this book on ants too though

9:17 http://mitpress.mit.edu/books/ant-colony-optimization

9:17 slipset: IMHO, when learning a new language/framework it's nice to be able to only focus on the language/framework and not worry about how to implement something.

9:17 zacts: maybe I could make an ant simulator

9:17 justin_smith: zacts: there are a few ways to drive music generation from clojure, you could pick one and maybe make a counterpoint engine, or a drum machine, or whatever style of music generation you are looking for

9:17 augustl: is there something like datomic's squuid available as a stand alone lib?

9:18 justin_smith: zacts: one of Rich Hickeys fist big demos of clojure concurrency was an ant simulator

9:18 zacts: oh really? coolio

9:18 dnolen: ClojureScript 0.0-2740 released, bunch of Windows fixes

9:18 justin_smith: augustl: iirc there is an under-documented method in java.util.UUID for generating SQUUIDs

9:19 slipset: https://gist.github.com/spacemanaki/1093917

9:19 ant-demo

9:19 tbaldridge: zacts: video of the ant-demo is in the last 30 min of this video: https://www.youtube.com/watch?v=dGVqrGmwOAw

9:19 zacts: oh nice! I'll check it out

9:20 justin_smith: zacts: make your own ants demo and then look at all the ways it is inferior to the one Rich Hickey mad :)

9:20 augustl: justin_smith: ah, will see what I can find :)

9:21 justin_smith: augustl: I think the key is how one constructs the mostSigBits and leastSigBits to the constructor

9:21 zacts: lol justin_smith

9:22 Glenjamin: that is a looong video

9:22 * Glenjamin adds to list

9:24 augustl: `new UUID(new Date().getTime(), new SecureRandom().nextLong())` seems to work

9:24 justin_smith: cool, didn't realize it would be that simple, but makes sense I guess

9:25 augustl: it's different from the one in datomic though

9:25 justin_smith: and that returns the right .timestamp value?

9:25 augustl: I get 0000014b-30eb-c56a-cba6-ff9a806cbef0, 0000014b-30eb-c56b-eacf-04128f2c0e06, etc

9:25 there are fewer zeroes in the one from datomic, fwiw

9:26 s/zeroes/leading zeroes/

9:27 clgv: zacts: I am implementing ACO algorithms in Clojure ;)

9:27 justin_smith: ,(.timestamp (UUID. (.getTime (java.util.Date.)) (.nextLong (java.security.SecureRandom.)))

9:27 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

9:29 justin_smith: augustl: another thing is that it doesn't actually create a time-based UUID (I don't know if that matters to you or not)

9:29 ,(.timestamp (java.util.UUID. (.getTime (java.util.Date.)) (.nextLong (java.security.SecureRandom.))))

9:29 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: Not a time-based UUID>

9:32 zacts: clgv: oh nice

9:32 clgv: perhaps I'll hang out with you here then

9:33 so hellofunk for music, clgv for ACO ants project =)

9:33 #clojure is really a cool channel so far with really smart people

9:41 samiswellcool: zacts: agreed

9:46 michaelr525: reify only supports interfaces hmm

9:46 maybe proxy instead..

9:49 donbonifacio: hum.. I have constant values that I use all over my app, each one is a map. Tried to use a record instead, and the tests take almost twice as much. Was expecting the opposite

9:54 justin_smith: donbonifacio: are you associating new keys that aren't part of the record, or dissociating keys that are part of the record?

9:54 donbonifacio: nop, they are totally constant, and only read data

9:55 I store them all (about 30 objects)

9:55 and then just read info from them

9:57 michaelr525: justin_smith: reify doesn't work with classes, only with interfaces and I can't seem to override the constructor with (proxy).. maybe I should try (gen-class) ?

9:58 justin_smith: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/

9:59 so you need a named type, that can be referred to statically from java that extends an existing base class?

9:59 according to cemerick's page that means you need gen-class, which is too bad

10:00 michaelr525: it doesn't have to be a named class..

10:00 I just need an instance of that classs

10:00 justin_smith: in that case proxy should work, if you can figure out how to override the default constructor?

10:01 michaelr525: i'll dig deeper ;)

10:04 zarkone: Hello all. i use figwheel started in repl for clojurescript. I add :source-map-true and :source-map-timestamp compiler options. CIDER can point the source location, but only the old one -- seems like :source-map-timestamp doesn't work...

10:05 both for Chrome and FF

10:13 michaelr525: no

10:13 doesn't seem like proxy can do it..

10:13 damn

10:22 justin_smith: ,(.newInstance (class (proxy [Object] [] (toString [] "silly"))))

10:22 clojurebot: #<Object$ff19274a sandbox.proxy$java.lang.Object$ff19274a@4bb1e2ee>

10:22 justin_smith: given a proxy, you can get its class and invoke the zero argument constructor

10:23 stuartsierra: augustl: Time-based "Version 1" UUIDs don't put the most significant time bits first.

10:24 Datomic squuids follow the format of random "Version 4" UUIDs but with the leading bits as time.

10:28 augustl: stuartsierra: ah, good to know, will look into that

10:29 clgv: zacts: hehe

10:44 michaelr525: justin_smith: well, I actually wanted to prevent the default contructor from being called. I thought that if I'd override it then it might work...

10:46 justin_smith: michaelr525: how did you go about implementing the constructor?

10:46 zacts: hum.. clgv what kinds of applications are you working on with ACO?

10:47 (if I may ask)

10:53 dysfun: hrm, how do i use libraries that don't use cljx from clojurescript if crossovers are deprecated?

10:53 in this case, i want to use flatland/useful

10:55 i know that the module i require doesn't do anything that clojurescript doesn't support

11:09 clgv: zacts: the classical ones - combinatorial optimization

11:09 zacts: oh neato

11:49 denik: Using, test.check, is it possible to generate hash-maps with matching, unique properties (e.g. ids)?

11:50 Two maps should share the same val at k

11:50 cemerick: denik: yes; see `bind` in its API

11:50 denik: ok

11:50 reiddraper: denik: use gen/fmap to add that key after generating the two values

11:51 cemerick: or that :-P

11:51 denik: what do you mean by two values

11:51 it would be a shared value

11:51 a pool of unique ids, for example

11:51 Glenjamin: (gen/fmap #(assoc % :k2 (:k1 %)) your-generator)

11:52 oh, i thought you wanted one hash-map with two values the same

11:52 well, the general idea is the same anyway

11:52 denik: okay, I'll try to figure it out

11:52 dweave: what does * mean around symbol names ie: *my-symbol*

11:52 denik: thanks everyone :)

11:53 Glenjamin: reiddraper: while you're here - if i want a number > or < some constraint, am i better off using choose, or gen/fmap with int?

11:53 reiddraper: denik: a good rule of thumb is that if something is statically generating (ex: apply unique, range-based ids), use fmap to deterministically add those values, instead of generating them

11:53 Glenjamin: probably choose

11:54 denik: reiddraper: copy that

11:54 Glenjamin: reiddraper: thanks - it's been super easy to far to expose stuff to JS

11:54 nic77: so guys im havin some trouble with graph theory i think

11:54 reiddraper: Glenjamin: happy to hear that :)

11:55 Glenjamin: i'm interested to try and put individual generators into npm modules somehow - like test.chuck but more granular

11:55 nic77: the wikipedia doesnt really explain the explanations lol i think im missing some building blocks

11:56 Glenjamin: although download size isn't really a constraint, being able to mix&match and move versions easily is pretty useful

11:58 nic77: these vertex and nodes and edges, whats with all of that

11:58 im not imagining something correctly

11:59 i thought it was a graphics thing

12:00 ill piece it together

12:00 this sucks though, its not clicking like things usually do

12:03 SagiCZ1: oh.. i was like.. this channel fell awfuly quiet today.. and then i noticed my scrollbar is stuck

12:03 nic77: http://en.wikipedia.org/wiki/Vertex_%28graph_theory%29

12:03 hey sag

12:03 yeah its gonna get sad here in a min

12:03 SagiCZ1: nic77: how come?

12:04 nic77: so that wiki link makes graph theory seem more like a venn diagram with arbitrary

12:04 im just a n00b with weak math thats why sag

12:04 but theres something about it i do understand, how to use it

12:04 SagiCZ1: nic77: that wouldnt sadden me

12:04 nic77: once i limp along

12:05 then i was projecting, giving

12:05 heck ill be back, have to tend to some animals

12:06 and turbotax

12:06 SagiCZ1: nic77: dont pay taxes to your turtle and feed the state some salad

12:07 nic77: hmm, is that a phrase i dont know of?

12:07 has a ring to it

12:07 SagiCZ1: nic77: no i just made that up, sorry

12:07 nic77: never heard that :D

12:07 well im in, good one

12:08 turtles would be easier tbh

12:08 were talkin old english mastiffs

12:08 im all for a high priced turtle bloodline

12:08 with registration papers

12:09 probably galapagos

12:09 hardly enough to start a registry though

12:09 SagiCZ1: nic77: ;)

12:09 nic77: id get into that biz

12:10 maybe

12:10 i dunno, depends on if it would end up animal smuggeling

12:10 or if it ends at uncle bills

12:10 thats how you know your into something one step above drugs

12:10 when product arrives at uncle bills

12:11 2 years ago in ohio next to me a wild animal refuge place had nearly all of its animals set loose

12:12 SagiCZ1: nic77: how many did you catch_

12:12 ?

12:12 nic77: none im in indiana

12:12 its just related a bit

12:12 like in one of those graphs

12:14 the laws and stigma with having tigers and crap, the dark element and shady dealings

12:14 that lead to lawsuits and crap

12:15 county and state came down on the guy so he turned them loose and i think killed himself

12:15 its a bad industry like the drugs, comes with alot of baggage

12:17 like stolen art or something that comes along with opposing armys/ideals

12:17 but the laws in ohio were laxed so people were able to carry out 80's cocaine cowboys type behavior when it came to zoo animals

12:17 i dont think they killed any animals but did have to round them up

12:17 it took a few days, maybe even a few fews

12:17 big cats and stuff

12:18 lion on the highway, bears even tigers oh my

12:18 arrdem: #clojure-offtopic please <3

12:19 clgv: arrdem: do you think the bot will follow those orders?

12:20 arrdem: clgv: I wasn't paying enough attention to decide it's a bot :P

12:20 just glanced over and saw a couple paragraphs of offtopiuc

12:20 clgv: arrdem: either a bot or a child ;)

12:20 nic77: around here a guy used to have a refuge, ran IMI irving materials

12:20 he got sued for capping the market and scaming extortion crap

12:20 concrete guys :D

12:20 they are just how they seem in the movies it seems

12:20 a guy in new york bought a dog from us and is currently slandering, hes a concrete bull too

12:20 is attempting to slander and blackball us currently

12:20 so becarefull when you mention turtles

12:20 arrdem: oh good.

12:20 nic77: hah, a bit of both

12:20 sorry guys

12:20 arrdem: amalloy_: fingerguns please. nic77.

12:20 nic77: what?

12:20 clojurebot: what is not a bug

12:23 Mr0: was that me? im having a keyboard issue at the moment

12:24 justin_smith: nic77: we have an off topic channel, please don't fill up this channel with off-topic stuff

12:24 we have a separate off-topic channel, that is

12:25 nic77: started out on topic just so you know

12:25 :D

12:27 motives are easy for some

12:27 i do want to know about the graph theory question

13:10 {blake}: What is "com.s

13:10 un.jndi.cosnaming.CNNameParser.CNCompoundName"? I just got a class not found on it. It went away as mysteriously as it arrived, but Google turns up nothing and I'm curious.

13:10 (Or at least, Google turned up nothing I could understand.)

13:11 justin_smith: {blake}: typically anything in com.sun is an implementation detail that shouldn't usually be used directly

13:11 {blake}: justin_smith: Yeah. I'm just wondering what I did to get a ClassNotFound on it!

13:14 tehgeekmeister: is there a core clojure thing or idiom for applying a bunch of functions to one collection?

13:14 H4ns: i'm wondering: how do other people deal with their dependency issues? we're spending hours and hours getting things sorted out with the help of :pedantic? true, but it is a very painful process and every single library update potentially creates hours of work fixing the dependency tree.

13:14 is our project just too big? we've not even started, really, but it already is a royal pain in the back.

13:15 {blake}: tehgeekmeister: Wouldn't that be comp?

13:15 tehgeekmeister: {blake}: i want to apply them independently, not sequenced

13:15 justin_smith: H4ns: I tend to be pretty conservative about using or updating libs

13:17 Glenjamin: tehgeekmeister: you mean like ##(->> [1 2 3] (map inc) (map #(/ 2 %))) ?

13:17 lazybot: ⇒ (1 2/3 1/2)

13:17 H4ns: justin_smith: that basically shifts the cost to later, but it is not really a solution, i'd think?

13:17 {blake}: tehgeekmeister: So you have collection C and you want a result of C1, C2, C3, C4 where f1, f2, f3 and f4 have been applied to C, respectively.

13:18 justin_smith: H4ns: why would I ever need to pay that cost? if a library has changed API I don't feel obligated to update all my code for the new API

13:18 Glenjamin: justin_smith: security updates, cascading upgrades

13:19 larger change when you do finally upgrade being harder than many incremental changes

13:19 dependency management is generally just hard

13:19 justin_smith: Glenjamin: fair enough. My security mostly rests on nginx and ssl.

13:19 sure, that's true

13:19 tehgeekmeister: {blake}: no, one set of functions, one collection. apply each function, and return a seq of the results

13:19 Glenjamin: if ring had a security vuln, you'd patch nginx to block the attack vector?

13:20 H4ns: we're now switching to flattening out our dependencies so that instead of relying on the version information that is in the jars that we use, we put all libraries with explicit versions into our own project as dependency.

13:20 Glenjamin: tehgeekmeister: something like ##(map apply [inc dec] (constantly 1))

13:20 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$constantly$fn__4178

13:20 justin_smith: Glenjamin: nginx, in practice, blocks most of the http attack vectors. I of course would update ring if/when something in ring was a security issue

13:20 H4ns: not sure if that is a great idea, but it sure sounds better than endless exclusions lists

13:21 Glenjamin: tehgeekmeister: sorry: ##(map apply [inc dec] (repeat 1))

13:21 lazybot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long

13:21 Glenjamin: dammit, repl hates me today

13:21 oh, i see why that doesn't work

13:21 anyway, the general idea would be to map function application over the list of functions

13:22 justin_smith: Glenjamin: in my clojure experience, the lib updates that cause dep management issues are the feature / API updates, a security update will be a drop in replacement and not cause code to break.

13:22 not that we can always count on backports if we are stuck on an old version of course

13:23 H4ns: justin_smith: like i said, you're shifting the cost to later.

13:23 Glenjamin: the cascading updates problem is more common i reckon

13:23 you need feature X from lib A, causing the whole tree to be invalid

13:24 justin_smith: H4ns: I have yet to need to change an app because of a security vulnerability in a clojure lib.

13:24 {blake}: Clojure does seem to be less susceptible to this than other languages, at least.

13:24 Glenjamin: {blake}: what makes you say that?

13:25 justin_smith: right, but there's no funamental property of clojure that makes that true

13:25 {blake}: Glenjamin: Ruby and Python experience. =P

13:25 Ruby, in particular, is like a kid with ADD.

13:25 tehgeekmeister: Glenjamin: ah, that makes sense

13:25 Glenjamin: getting back into the functional mindset still

13:25 justin_smith: Glenjamin: immutability actually has some nice consequences regarding security holes, actually.

13:26 Glenjamin: it's just that there's a relatively small number of libraries, and the maintainers are still using them

13:26 give it another 5 years of dependency fragmentation

13:26 {blake}: Everything is deeply intertwingled. And minor revisions tend to invalidate reams of code.

13:26 justin_smith: and immutable data structures (at least their pervasiveness), is definitely a property of clojure

13:26 Glenjamin: could you elaborate? i think we get benefits from dynamic typing in this space

13:26 {blake}: Glenjamin: Fair point, but I do think there's a priority in Clojure of interoperability.

13:27 I love the way Noir split itself, e.g.

13:28 justin_smith: Glenjamin: also in terms of upgradability, idiomatic clojure code tends to be coded against interfaces and not concrete types, which tends to reduce brittleness.

13:29 but yes, dependency management can be a pain in the ass, even in clojure

13:29 Glenjamin: do protocols have to do complete implementations?

13:29 justin_smith: not at all

13:29 Glenjamin: that's a big +1 for this then

13:29 new interface method doesn't break existing users

13:29 justin_smith: right

13:30 in pure clojure (not using java), interfaces don't even need complete implementations

13:30 Glenjamin: oh? i thought you had to declare all methods?

13:30 justin_smith: not from clojure, no

13:31 llasram: Welllll, but unimplemented protocol methods will throw an exception

13:31 So it isn't that useful a feature (IMHO)

13:31 justin_smith: llasram: if you call them

13:31 llasram: we are talking about libs breaking because a spec changed

13:31 llasram: Ah,

13:31 nm

13:31 Apologies for not reading full context before jumping in

13:32 H4ns: i think the basic problem is that one cannot express imprecise dependencies in leiningen

13:32 (or maven, ftm)

13:32 justin_smith: Glenjamin: I don't want to get too arrogant and say that we don't have version problems or security issues in Clojure, that would be foolish

13:32 Glenjamin: i think its relatively accurate at the moment

13:32 but not because of anything that's a property of the platform

13:32 justin_smith: but there are measurable ways that Clojure does things better than average, and I think if you are doing a lot of frequent upgrading you might be doing unneeded work

13:33 Glenjamin: https://groups.google.com/forum/#!topic/clojure/WuS31RSiz_A

13:33 "Dependencies suck, so stop sharing code please"

13:33 to tl;dr it somewhat uncharacteristically

13:34 perplexa: heya

13:35 i have a midje test and a function with 2 external dependencies that i want to test. i see that there is the (provided) statement to do that stuff, but i don't quite understand how i would use that to rewrite functions in different namespaces

13:36 my function (execution-epochs) calls (h/last-execution) and (t/now) and i want to mock those, but (provided (h/last-execution :test) => (t/date-time 2015 2 27 23 0 0 0)) does not seem to give the desired rresults

13:36 and tips where to start? ;/

13:36 Glenjamin: anyway, the above problem is why i keep thinking about writing a package manager for utility functions

13:38 tbaldridge: perplexa: instead of trying to test that way, build your system via modules, if you want to mock date-time, make date-time a protocol that you can pass a implementation of to execution-epochs

13:39 you gain two things a) more extensible code, b) less reliance on wacky macros like providing

13:39 *provided

13:39 perplexa: hmyeah the code is bad ;p

13:40 my actual problem is something else, i just wanted to write a test for the function to be able to write something new that still behaves the same, but i guess i'll have to do that without a test ;x

13:43 was using clj-time 0.9.0's periodic function, it somehow stopped working for me, i tried to figure out why as it was working previously. eventually downgraded to 0.8.0, but that unfortunately doesn't support an end-datetime, but the funtion itself didn't cause errors anymore. so i upgraded again and usddenly 0.9.0 was working in my repl again, but still fails on a production machine. the function's code: ...

13:43 ... https://github.com/clj-time/clj-time/blob/master/src/clj_time/periodic.clj and i was getting "ClassNotFoundException clj_time.periodic$periodic_seq$fn__4142 java.net.URLClassLoader$1.run (URLClassLoader.java:366)" in the repl and the caught exception on the other machine is "No matching method found: multipliedBy for class org.joda.time.Period".

13:44 the class not found exception magically disappeared after down and upgrading clj-time, though ;/

13:44 justin_smith: perplexa: maybe you had some stale compiled artifacts that didn't get cleaned properly?

13:45 perplexa: justin_smith: lein clean should do the trick, though?

13:45 justin_smith: yeah

13:46 you could run lein deps :tree to verify you are seeing the version you expect pulled in

13:49 perplexa: justin_smith: that looks horrible

13:49 hadoop ftl ;<

13:49 zacts: hellofunk: yo man

13:50 hellofunk: zacts: 'sup dude

13:50 zacts: hey, so what do you think about those computer music books?

13:50 justin_smith: perplexa: bad dep tree?

13:51 hellofunk: amalloy_: hickey's strange loop transducer's talk and the wikipedia page for folds seem to provide different explanations of the difference between foldl and foldr

13:52 amalloy_: hickey's seemed to imply that foldr was basically a cons operation, and foldl is a loop operation, but in both cases the supplied initial value was used from the start of the list. the wiki page diagrams suggest foldr uses the supplied default at the end of the list?

13:53 perplexa: justin_smith: tells me about lots of exclusions that i should consider

13:54 dnolen: Facebook announced React Native - target Android & iOS w/ JS - too bad ClojureScript isn't on board yet w/ React ;)

13:54 justin_smith: hellofunk: if you cons, the first value you add ends up at the end

13:54 ,(reduce cons () (range 10))

13:54 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

13:54 justin_smith: ,(reduce #(cons %2 %) () (range 10))

13:54 clojurebot: (9 8 7 6 5 ...)

13:55 justin_smith: or is that a non-sequitor?

13:55 hellofunk: ,(reduce #(cons %2 %) [] (range 10))

13:55 clojurebot: (9 8 7 6 5 ...)

13:55 arrdem: hellofunk: conj

13:56 fast append fts

13:56 *ftw

13:56 justin_smith: arrdem: I was making a point about cons / fold

13:56 it would have been simpler code, but less clear a point, if I used conj

13:57 hellofunk: justin_smith: but reduce in clojure is a foldl so not sure you can really get the proper operation expressed

13:57 arrdem: justin_smith: understood. my read of hellofunk's last was that s?he was trying to show the appending behavior.

13:57 justin_smith: ahh, rightr

13:58 dino-: I just started working on clojure-koans. When I do `lein koan run`, after a test fails, it just hangs there and doesn't exit and I have to use ctrl-c. Is that normal?

13:58 hellofunk: for example, if your reduce operation is + and you supply init of 5 and a sequence of (range 5) my interpretation is that a foldr would start with 1 + 2, and the 5 doesn't enter the picture until the end

13:59 that's the suggestion from the wikipedia diagram, but perhaps i am interpreting it wrong

14:00 (actually i meant the first 2 would be 0 + 1)

14:00 justin_smith: hellofunk: are foldl / foldr about the order of the operations, or the effective order in which they are applied? Would it not still be a valid foldl if the compiler noticed that + is associative and mixed up the order to optimize it?

14:00 hellofunk: justin_smith: well, that is indeed the question i'm asking

14:01 justin_smith: hellofunk: at least in haskell, order of execution is undefined unless you explicitly use something like a monad that enforces ordering

14:01 I don't know how far we can generalize that though

14:01 hellofunk: justin_smith: checkout these two diagrams for foldl and foldr http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29

14:03 justin_smith: based on these, what would you say are the first two args to a foldr of + over (range 5)

14:04 dino-: Oh, I see, when I edit and save (in another shell) while that `lein koan run` is still running, it unblocks and keeps going. cool!

14:06 justin_smith: hellofunk: 4 and 3. But what I was trying to get at is that "first" doesn't have to determine order of computation, as long as your transformation preserves the correct result

14:07 hellofunk: justin_smith: it would seem to me that a non-lazy version of foldr with reduce would simply be to reverse the sequence first, then proceed with a normal reduce?

14:09 justin_smith: when I read that diagram, foldr preserves order

14:09 also, I think foldl and foldr are terrible names that makes it much too easy to accidentally swap them

14:09 and I would have named them fold and dlof if I invented them

14:10 hellofunk: oh, wait, the operation is cons, so yes, reversing once and then reducing with cons would preserve order

14:10 sorry

14:10 hellofunk: it's not clear to me how laziness relates to this. if this is a foldr approach: 1 + (2 + (3 + (4 + 5))) then what does it mean for this to be lazy? lazy in the sense that you could get just the result of the operation over the first 2 items rather than the whole? in which case, how is that possible when each item is an operation that requires the entire rest of the sequence operated on as well?

14:10 justin_smith: double reverse

14:12 hellofunk: how did laziness come into play here again?

14:13 hellofunk: justin_smith: foldr is recognized as a lazy fold, which does not exist in clojure, while foldl is not lazy. amalloy_ and the hickey video have both pointed this out, but i'm trying to see what that means

14:14 justin_smith: hellofunk: I think that this means the difference between doing a cons at each step, vs. creating a new lazy-seq thunk for each step

14:14 these give you opposite effective orderings

14:14 specifically for the collection building (which can be lazy / non-lazy)

14:15 hellofunk: justin_smith: actually i just saw that laziness is discussed about halfway down that wiki page

14:16 hiredman: laziness in clojure is tied to particular constructs, like a lazy-seq, in haskell were fold is lazy, everything is lazy, so if you do a fold with +, you get a value that is effectively a promise to give you the value of all those additions on demand

14:17 in clojure + is not lazy, and numbers are not lazy, so a fold that produces a number cannot be lazy

14:17 Glenjamin: dnolen: do you think cljs would be able to target React Native?

14:18 hellofunk: justin_smith: those diagrams don't really do much to clarify the issue, and in fact i think lead to more confusion

14:19 hiredman: this issue is more about foldl and foldr and why foldr is lazy and foldl isn't, i'm trying to understand where the lazyiness comes into play with a foldr structure like this: 1 + (2 + (3 + (4 + 5)))

14:19 hiredman: hellofunk: that is a bad structure to try and understand with

14:20 hellofunk: the order of the reduction doesn't matter in that structure

14:21 justin_smith: hellofunk: they are helpful in that they emphasize the fact that it isn't about order of evaluation, it is about the ordered structure of the result, and which nodes have which other nodes as their tail in the resulting tree

14:21 whether that tree is an evaluation tree or a literal tree (because your function was a collection building one)

14:22 hellofunk: and as hiredman already mentioned, even in a lazy language, you get a thunk that forces all of those additions - you can't consume that partially

14:23 also, if you wanted a reducing function, - may be a better example, since order matters with -

14:24 hellofunk: good point

14:24 hiredman: the laziness doesn't really matter with numbers, the laziness comes in to play when you are building a collection (often a list) in the reduction

14:25 justin_smith: exactly

14:25 hellofunk: i see, so thinking of these examples with cons in mind is the best way to visualize

14:27 hiredman: if you start with [1 2 3 4] and right fold cons you get (cons 1 (cons 2 (cons 3 (cons 4 nil)))) and left fold (cons 4 (cons 3 (cons 2 (cons 1 nil))))

14:27 hellofunk: hiredman: that's helpful

14:28 hiredman: the right fold has the output that corresponds to the first input element first, which, if the whole cons process is lazy, means you can grab the first element without ever doing anything else

14:28 justin_smith: hiredman: wait, wouldn't a right fold consume the leftmost element of the sequence first?

14:28 hellofunk: justin_smith: actuall the wiki diagram lines up with the hiredman example, i think it's clicking with me

14:28 hiredman: the left fold has to descend the entire structure in order to return the first result

14:28 justin_smith: oh, never mind, that's what you said

14:29 I just misread what he was saying

14:29 hellofunk: hiredman: that's actually quite illuminating, thanks

14:42 amalloy: another way to say what hiredman is saying is that foldr can be lazy iff the folding function is lazy in its accumulator. a foldl looks like (f (f (f (f 1 2) 3) 4) 5), which means you can't really get anything useful from the beginning of the sequence, since those are buried in more calls to f

14:43 but a right fold looks like (f 1 (f 2 (f 3 (f 4 5)))), so you if f is something like "if the left number is odd, return it, otherwise return the right number), you can do that without even looking at (f 2 ...)

14:48 hellofunk: amalloy: it's confusing to me to call the clojure reduce a foldl since it doesn't at first seem to meet either the foldl or foldr patterns. (reduce (flip cons) [] [1 2 3]) starts with (cons 1 []) and technically you could stop right there if you didn't need the rest.

14:50 amalloy: hellofunk: but you can't, because there are no lazy data structures in use there

14:50 hellofunk: amalloy: so is the burden for laziness on the data or on the function? ie the consumer or that which is consumed?

14:50 amalloy: the language

14:51 clojure's evaluation semantics are eager, so no foldl can ever be lazy

14:51 (no foldr either)

14:51 hellofunk: amalloy: is not a lazy foldl possible in clojure, maybe not with reduce?

14:51 stuartsierra: reductions!

14:52 amalloy: well, kinda

14:52 justin_smith: I could imagine using reductions to eg. determine with laziness whether the sum of a given collection of positive numbers was greater than some threshold

14:52 amalloy: reductions lets the consumer of the fold choose when to stop folding (by not requesting any more elements), but it doesn't let the fold function itself decide

14:52 stuartsierra: not the same as foldl, but gives you a sequence of "intermediate" reduce results.

14:53 hellofunk: i'm familiar with reductions but it seems like a cheat in the theory of folding

14:53 felixflores: does anyone know how to insert a record's default values using korma?

14:53 gfrederi`: reduce can do that via reduced though, right?

14:54 aaelony: I thought I had heard that Incanter 1.9 or 2.0 was available somewhere but I only see 1.5.7-SNAPSHOT in https://github.com/incanter/incanter... Am I looking in the wrong place?

14:54 felixflores: I tried something like (insert article (values {}))

14:54 it doesn't work

14:54 amalloy: gfrederi`: yes. that's the one i think of as a cheat, though

14:54 hellofunk: gfrederi`: well reduced is also a bit of a cheat. i'm curious about the higher theory of how folds work in a pure functional context

14:55 i would probably greatly benefit from studying haskell for awhile

14:56 gfrederi`: oh okay I didn't know we had ruled out cheating

14:57 justin_smith: "#clojure: oh, okay, I didn't know we had ruled out cheating"

14:57 hellofunk: gfrederi`: for example, i don't think haskell requires the notion of either "reductions" or "reduced" to achieve these basic features of lazy folding

14:57 justin_smith: gfrederi`: makes a nice tagline I think

14:57 aaelony: ah... looks like the develop branch is at 1.9.1-SNAPSHOT level ... (nevermind)

14:58 xyz_: Hello, can someone help me iterating over a nested map and pass the path (ie. the [:key1 :key2]) to my mapping function ?

14:59 amalloy: gfrederi` sounds like an italian name. signior frederi

14:59 justin_smith: xyz_: so you want to get to every nested value of a map, and get the path to that thing from the root?

15:00 hellofunk: justin_smith: even if that' not xyz_ 's question, it's one i'd be curious about

15:00 xyz_: @justin_smith exactly

15:01 amalloy: http://stackoverflow.com/a/21769786/625403

15:01 xyz_: the function should receive the key, value and path (but the path could be enough, right ?)

15:01 amalloy: just needs a slight modification to use the vals as well as the keys

15:02 or take what's there and map get-in over it

15:02 justin_smith: (inc amalloy)

15:02 lazybot: ⇒ 217

15:02 justin_smith: that's awesome

15:02 dino-: I'm very new. A little confusing you can't use nil in place of '()

15:03 justin_smith: (inc puredanger) ; for writing it

15:03 lazybot: ⇒ 31

15:03 dino-: I guess it doesn't mean "the empty list"

15:03 xyz_: @amalloy ok I'll try and be back thank you (I'm still a Clojure noob so even if I find it I'll ask for feedback). Thank you

15:03 justin_smith: dino-: () is an empty collection, nil is the null pointer

15:03 dino-: in many languages, a null pointer means "empty list", this is not one of those

15:04 dino-: justin_smith: thank you

15:04 justin_smith: dino-: the function seq will give you nil for an empty list, or an equivalent sequence for any other sequential though

15:04 ,(seq ())

15:04 clojurebot: nil

15:04 justin_smith: ,(seq '(1 2 3 4))

15:04 clojurebot: (1 2 3 4)

15:05 justin_smith: dino-: there is also the function not-empty, which unlike seq preserves the collection's type, but returns nil for empty input

15:05 ,(not-empty {})

15:05 clojurebot: nil

15:05 justin_smith: ,(not-empty {:a 0})

15:05 clojurebot: {:a 0}

15:05 justin_smith: ,(seq {:a 0})

15:05 clojurebot: ([:a 0])

15:05 dino-: huh, ok

15:06 justin_smith: that should suffice for eg. translating common lisp code where they use empty as false in loops

15:07 (inc amalloy)

15:07 lazybot: ⇒ 218

15:07 justin_smith: just scrolled down to your answer on that keys-in thread

15:08 amalloy: a lot simpler indeed, but slightly inconsistent

15:08 dino-: Ok, thanks again

15:12 amalloy: justin_smith: i really love that pattern for exploring a decision tree

15:13 (fn paths [node] (if (done? node) '(()) (for [choice (choices node), subpath (paths (make-choice node choice))] (cons choice path)))) can apply to all sorts of things

15:14 justin_smith: amalloy: maybe it should have a name?

15:15 amalloy: i've thought about it. it seems like most cases where you'd want to use it, though, it's shorter/easier to inline the logic than to pass in the three necessary functions

15:15 justin_smith: I bet it is the equivalent of some graph algo I don't know the name of

15:15 amalloy: justin_smith: i mean it is literally just DFS

15:15 justin_smith: amalloy: right, but even if it is sufficiently abstracted, we can name it

15:15 OK

15:15 oh, right

15:15 d'oh

15:15 clojurebot: Pardon?

15:15 hellofunk: amalloy: what is DFS mean?

15:15 justin_smith: clojurebot: d'oh

15:15 clojurebot: Cool story bro.

15:16 justin_smith: depth first search

15:16 hellofunk: oh, word

15:16 amalloy: the trick is figuring out how to think of your problem as a search tree so that Depth-First Search makes sense for it

15:16 justin_smith: right, that is often the issue with graph / tree stuff

15:16 the hard part is seeing the graph / tree

15:16 after that it's rote

15:16 hellofunk: "for" is pretty much a depth first logic with cut options, sorta

15:17 justin_smith: hellofunk: plus combinatoric expansion

15:17 amalloy: justin_smith: i feel like this paths function is *almost* tree-seq

15:17 justin_smith: yeah, it's close, but it preserves some info tree-seq does not

15:17 it has more points of articulation

15:19 SagiCZ: haha.. i finally got rid of that pesky number one behind my nick. Behold!

15:19 hellofunk: ,(source for)

15:19 * SagiCZ finally ok

15:19 clojurebot: Source not found\n

15:19 justin_smith: hellofunk: oh man, the source of that is insane

15:19 have fun reading it!

15:19 hellofunk: i thought there was a source finder on here

15:19 amalloy: $source for

15:19 lazybot: for is http://is.gd/x33p56

15:19 amalloy: ~def for

15:19 benaiah: anyone know of a good tutorial for writing command-line applications in clojurescript?

15:19 justin_smith: woah, interesting use of notification

15:20 amalloy: yeah, i don't really understand why clojurebot sends that as a notice, compared to most of the stuff it says

15:20 slipset: one could argue that the source for for looks quite like the source for doseq

15:21 anyone in for a slight refactor to pull out the common stuff?

15:21 justin_smith: slipset: they have a lot in common

15:21 slipset: justin_smith: I would imagine

15:21 amalloy: "slight refactor". best joke of the day so far

15:21 hellofunk: amalloy: weird they link to different source files for for

15:21 slipset: ~for

15:21 justin_smith: slipset: in clojure.core perf is more important than cleanliness in general

15:21 clojurebot: for is like doseq, but for values instead of side effects

15:21 amalloy: hellofunk: they're running different versions of clojure

15:21 slipset: ~doseq

15:21 clojurebot: doseq is like for, but for side effects instead of values

15:21 amalloy: (inc clojurebot)

15:21 lazybot: ⇒ 46

15:21 amalloy: and whoever taught him that

15:22 slipset: given the docs I would imagine they have something in common

15:22 hellofunk: (inc whoever)

15:22 lazybot: ⇒ 1

15:22 hellofunk: well, just trying to help

15:23 slipset: justin_smith: I've come to understand that perf is quite important, but still.

15:25 justin_smith: slipset: I promise, a PR against core that does not at least keep performance as good as it is currently has very little chance of being accepted (unless it improves correctness of course)

15:25 tbaldridge: personally I think doseq should move to something that uses reduce

15:25 that way doseq over a vector can use the vector's internal reduce logic

15:26 slipset: tbaldridge: and be faster :)

15:28 {blake}: benaiah: Nope. But if you're willing to take the startup time hit, it shouldn't be any different from any other kind of Clojure app.

15:28 gfredericks: (defmacro doseq "shells out to DOS to determine the equality of x and y" ...)

15:28 justin_smith: {blake}: point is you compile once and run the js, so it *eliminates* the startup time hit

15:28 benaiah: {blake}: the startup time hit is the reason I wanted to write it in cljs instead of clj. Doesn't seem to be much support for that atm.

15:29 justin_smith: if you are repeatedly using the same utility, which is very common in the command line world

15:29 benaiah: it would be very nice to have a turnkey way to generate a cljs command line util, I agree. I don't know if one exists or not.

15:30 benaiah: justin_smith: perhaps I'll write one. The node CLI tooling is pretty well documented

15:30 justin_smith: benaiah: that would be awesome

15:30 perhaps as a lein or boot task

15:32 benaiah: probably the best approach is to make a template that has the infrastructure for a command line app (simple arg parsing, ready to compile all the cljs into one target, generates a batch file that runs that via node maybe?)

15:35 {blake}: benaiah, justin_smith: Oh, clojureSCRIPT. Duh. Yeah, that makes a difference.

15:36 That would be cool.

15:40 zacts: huh, see I'm thinking of using clojurescript for cli apps too

15:40 jvm clojure is just too slow for startup times

15:40 justin_smith: something in the wind, clearly

15:41 zacts: it can be much faster if you uberjar, or with a repl if you use fast-trampoline or use the standard repl instead of nrepl

15:41 zacts: you know what would be cool would be the clojure equivalent to the scsh (scheme UNIX shell)

15:41 oh let me check that out

15:41 justin_smith: zacts: that actually would be an awesome thing to port to clojure, I would love that

15:41 zacts: yeah, perhaps I may look at it within the next few months for a fun side project

15:41 justin_smith: zacts: faster lein is documented here https://github.com/technomancy/leiningen/wiki/Faster

15:41 slipset: https://github.com/Raynes/conch

15:42 zacts: I already have too many projects at the moment, and I'm still a newbie

15:42 justin_smith: slipset: yeah, conch would actually be a decent starting point to doing something like scsh

15:43 zacts: nice

15:46 justin_smith: I like this trick: ##(update-in {:a 0} [:b] (fnil identity 42))

15:46 lazybot: ⇒ {:b 42, :a 0}

15:46 justin_smith: (here I don't ever want nil as a value, so absence vs. nil value is a non-issue)

15:47 zacts: I wish I had some good books on design

15:47 designing abstractions

15:48 amalloy: so justin_smith, i tried writing out a generic tree-search algorithm and applying it for the keys-in problem. it's not really better IMO: https://www.refheap.com/866bb537b31215e53e04713c1

15:48 zacts: but perhaps that's something that can really only be learned from experience

15:48 opqdonut: justin_smith: I usually just merge...

15:48 amalloy: needs a million dang parameters

15:48 zacts: SICP I think approaches this though

15:48 opqdonut: ,(merge {:b 42} {:a 0 :c 1})

15:48 clojurebot: {:a 0, :c 1, :b 42}

15:49 justin_smith: opqdonut: right, that is similar, but it does the wrong thing if the final map has {:b nil}

15:49 opqdonut: remember I said I didn't want nil values

15:49 opqdonut: oh right

15:49 l1x: if somebody is bored, what is the Clojuresq version of this https://gist.github.com/l1x/9f4c6d68e0a407185277?

15:49 justin_smith: this way I can skip a winnowing step

15:51 l1x: I am 80% sure the answer involves using for

15:52 amalloy: haha yes

15:52 l1x: justin_smith: :)

15:52 amalloy: it is the same dfs, by the way

15:52 to solve l1x's problem

15:52 l1x: justin_smith: how can you recur with for?

15:52 justin_smith: amalloy: yeah, that is so parameterized that you may as well type the full thing out and just have the name for the pattern

15:52 amalloy: it's a tree search over a tree with branching factor 10 and depth number-digits

15:52 justin_smith: (regarding that refactor)

15:53 l1x: amalloy: hmm yeah

15:55 amalloy: &(map (partial apply str) ((fn perms [num-digits] (if (zero? num-digits) '(()) (for [perm (perms (dec num-digits)), n (range 10)] (cons n perm)))) 2))

15:55 lazybot: ⇒ ("00" "10" "20" "30" "40" "50" "60" "70" "80" "90" "01" "11" "21" "31" "41" "51" "61" "71" "81" "91" "02" "12" "22" "32" "42" "52" "62" "72" "82" "92" "03" "13" "23" "33" "43" "53" "63" "73" "83" "93" "04" "14" "24" "34" "44" "54" "64" "74" "84" "94" "05" "15" "25" "... https://www.refheap.com/96597

15:56 amalloy: or i guess if you want it to do them in the other order, ##(map (partial apply str) ((fn perms [num-digits] (if (zero? num-digits) '([]) (for [perm (perms (dec num-digits)), n (range 10)] (conj perm n)))) 2))

15:56 lazybot: ⇒ ("00" "01" "02" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30" "31" "32" "33" "34" "35" "36" "37" "38" "39" "40" "41" "42" "43" "44" "45" "46" "47" "48" "49" "50" "51" "52" "... https://www.refheap.com/96598

16:00 amalloy: l1x: does that make sense?

16:00 l1x: huh

16:03 amalloy: thanks

16:06 slipset: amalloy: same discussion, different place? http://stackoverflow.com/questions/18246549/cartesian-product-in-clojure

16:09 amalloy: slipset: yes

16:10 benaiah: calling `lein cljsbuild once` on this barbebones repository: https://github.com/Benaiah/cljs-test yields the following error: https://www.refheap.com/96599, which I keep getting every time I try to use cljsbuild on several different starter templates. Anyone have any idea what's going on?

16:13 tcrayford____: anybody ever got ring's wrap-reload middleware working with tools.namespace and component/etc?

16:18 benaiah: does this project.clj look correct for a clojurescript project? https://github.com/Benaiah/cljs-test/blob/master/project.clj

16:31 notbrent: benaiah: https://github.com/swannodette/mies-node-template

16:31 you need to make some changes to your project.clj

16:31 (sorry if that was answered already, my irc client timed out)

16:32 dnolen: benaiah: looks ok though that build is missing an :id

16:32 xyz_: Hello, this is a follow-up question to getting the path of the keys in a map. Can the value returned from the mapping function replace the value in the previous map (constructing a new map)?

16:32 benaiah: notbrent: no, yours was the first answer. thanks, that's quite helpful

16:33 justin_smith: xyz_: do you need both the paths and to do the mapping, or would just the mapping suffice? because if the latter you may just want to use clojure.walk/post-walk to update leaves

16:34 xyz_: I can't use walk because I need to get a value from another map (a symetrical map if you will)

16:34 clojurebot: It's greek to me.

16:35 xyz_: @justin_smith sorry, the paths and what ?

16:35 justin_smith: xyz_: ahh, OK. In that case I would first get all the paths, then do a reduce over each of the paths of the map, doing the updates as needed

16:35 xyz_: if you just needed to do the updates of leaves, and did not have a separate use for the path to that leaf, postwalk would be simpler. But you do have a separate use for the path.

16:36 xyz_: justin_smith: yes the problem I had was with the path

16:36 justin_smith: I'm not sure I get the reduce idea completely yet though

16:36 justin_smith: so now you have a function that returns all the paths, so do a reduce over all the paths, with the initial map as your init value

16:36 and for each path either update or not as needed with the help of the other map

16:37 xyz_: justin_smith: let me get back to digging ^^ I'll come back again

16:37 amalloy: xyz_: it sounds like you are trying to solve some larger problem, and you've been asking about sub-problems. that's a good instinct, avoid dumping everything on #clojure all at once, but i worry that you're breaking it down into the wrong subproblems. what is the overall thing you are trying to achieve?

16:38 justin_smith: xyz_ (reduce (fn [m path] (assoc-in m path update (get-in m2 path))) initial paths) ; something like this is what I meant

16:38 where the update function looks at the path, and the two maps, and either returns the new value to use at that place (usually the original I would guess)

16:38 xyz_: amalloy: xy problem, I know :) I am trying to convert a map of string values into a map of correct values (correct as defined by the type of the values of the first nested map). Not sure if I'm clear.

16:39 justin_smith: ok I'll try to digest that. Thank you

16:39 amalloy: so you have a "template map" or a schema or something, describing the types that another map should have, and you want to walk over the second one and modify its stuff to be the right type

16:40 xyz_: amalloy: exactly. like a schema or a merge

16:40 hiredman: imagine the maps are flat instead of nested

16:41 {:a {:b 1}} -> {[:a :b] 1}

16:41 do the same thing you would do for the flat maps, but use assoc-in instead of assoc

16:41 amalloy: i don't actually use prismatic/schema myself, but this sounds like something it wants to do: https://github.com/Prismatic/schema#transformations-and-coercion

16:42 xyz_: amalloy: yes. This is an exercise for me, and I can't read cljx yet ^^

16:43 hiredman: I think that this is what amalloy hinted at earlier ? with the keys-in function ?

16:43 amalloy: well. you don't need keys-in if your schema map is structured like {[:a :b] String} instead of {:a {:b String}}

16:44 but of course you can use keys-in on the latter to produce the former

16:44 xyz_: amalloy: it's structured like a normal map (the latter)

16:44 amalloy: yes I'll try that. That's a lot of info right now, let me get back to you guys Thanks again !

16:51 gfredericks: oh man core async depends on a sooper old analyzer

16:51 adnauseaum: clojure is gay and i hate it

16:51 benaiah: notbrent: thanks a lot - that minimal project has made the cljs stuff much clearer than the documentation was able to alone

16:52 notbrent: :) no problem - dnolen did all of the work, i just linked to it ;P

16:59 dbacar: Hi, anyone here with experience regarded to Jsoup?

16:59 adnauseaum: jsoup is gay and i hate it

17:00 justin_smith: amalloy: ping

17:00 dbacar: really?, it seems nice , what would you recommend?

17:00 adnauseaum: justin_smith: ping

17:00 i'd recommend something that's less gay

17:00 amalloy: so does anyone think it's crazy that i like to respond to pings by just mashing my fingers on the keyboard instead of typing out a proper pong?

17:01 justin_smith: hehe

17:01 I think this guy wants to be restricted from using out channel

17:01 adnauseaum: nah bruh

17:01 amalloy: oh hey, i forgot i can do that

17:01 adnauseaum: we gucci yo

17:01 AeroNotix: oh cool, someone to add to my ignore list

17:01 adnauseaum: woah bruh u talkin shit? talk shit get hit

17:01 AeroNotix: yep. It's offical.

17:01 amalloy: i wonder if i can remember how

17:02 AeroNotix: adnauseaum: peace

17:02 hiredman: I bet you just repsond with garbage to a syn too

17:02 adnauseaum: pzl8

17:02 reecies peaceis


17:02 dbacar: there is a static class in Jsoup called Document.OutputSettings, i can't find how can i add it to my ns declaration, any suggestions?

17:03 justin_smith: dbacar: (:import whatever.Jsoup.Document.OutputSettings) I would think

17:04 of course make sure you have your project set up to pull in the dep too

17:05 oh, (:import org.jsoup.nodes.Document.OutputSettings) - or looks like since it is an inner class you need to do (:import org.jsoup.nodes.Document) then use Document$OutputSettings

17:07 dbacar: justin_smith: thank you, it worked, i tried the following and it throws an classnotfoundexc, do you know why?

17:07 [org.jsoup.nodes Document Document.OutputSettings

17:07 Attribute Attributes Comment DataNode

17:07 Element TextNode]

17:07 inside an :import

17:07 travisrodman: amalloy: thanks for handling that.

17:07 justin_smith: dbacar: it's not Document.OutputSettings, it's Document$OutputSettings, that's the syntax for an inner class

17:08 and I don't think you can import the inner class (not 100% sure of that though)

17:08 dbacar: i have a long way to go :(

17:08 justin_smith: amalloy: seconding that, thanks

17:09 amalloy: justin_smith: you can import inner classes

17:09 dbacar: justin_smith: it seems you can import inner classes the way you told

17:09 amalloy: they're just ordinary classes with funny names

17:11 justin_smith: oh, that's great

17:11 I just never had to do it yet

17:12 tcrayford____: get used to $ errywhere

17:12 * justin_smith has a perl flashback.

17:12 * AeroNotix doesn't see it that much :S

17:19 csd_`: If I have a hash map tracking something like users, which its keys indexed to usernames, and I want to check whether a username exists already, would it be more efficient to check a separate hash-set, or to get the hash-map's keys and check those?

17:19 justin_smith: csd_`: contains?

17:20 csd_`: hash-set would contain strings, hash-map would contain maps of user state

17:20 keyed by username

17:20 justin_smith: why separate the keys into a hash-set?

17:21 csd_`: im just wondering whether that would be more efficient for purposes of checking if a name exists already

17:21 justin_smith: I am suggesting the function, called "contains?", which should be no slower than hash-set lookup

17:21 csd_`: i'm writing a toy irc server and am thinking about data structures

17:21 justin_smith: in case that wasn't clear and that just looked like a question

17:21 cool

17:22 another options is find

17:22 csd_`: is it poor form to pass global state as a variable to functions, or would it be better to keep it as a global atom

17:22 justin_smith: ,(find {:a 0} :a)

17:22 clojurebot: [:a 0]

17:23 dnolen: csd_`: hash set is backed by a hash map, so no won't be faster

17:23 justin_smith: csd_`: well, if you pass it to each function, it doesn't have to be global any more

17:23 you can just call it "accumulated state"

17:23 and the fact that it never branches or backtracks is an implementation detail

17:24 and actually that is better than a global atom, if your design can pull it off

17:24 csd_`: i'm guessing it wouldn't work once i introduce concurrency

17:24 justin_smith: csd_`: the reason I suggest find is that it unambiguously tells you if the value was there, and gives you the existing value if it is

17:24 csd_`: yeah, once you have concurrency you probably want an atom or ref

17:25 csd_`: justin_smith: would you define either as a global?

17:25 justin_smith: the atom, yeah

17:25 if you are just threading a value through, no, not as global

17:25 csd_`: ok

17:25 justin_smith: but I would combine the atom with passing the value, if you do it that way

17:26 rather than doing lookup at each processing step in one request

17:26 csd_`: i havent worked with refs yet, haven't had any need

17:26 justin_smith: and then when done with it, put that back in the atom

17:26 yeah, usually an atom will suffice, but for parallel interdependent modification refs can be a perf boost

17:32 {blake}: Is there a clever way, given the compojure format of (-> (handler) (middleware) (middleware) (middleware) (middleware)), to add some kind of wrapper that tracks each request as it mutates?

17:32 I guess I could macro it up.

17:33 justin_smith: {blake}: there is a debug-middleware you can place between any two of the others

17:33 because hey, all the middleware are are wrappers, so throw it in the chain

17:34 or you could hack together a replacement for -> that also debugs the intermediate values

17:34 {blake}: justin_smith: Thanks. I was just thinking "SHOW ME ALL THE THINGS!" but that's probably not worth it.

17:34 justin_smith: Ha! Yeah, I'm probably not that ambitious right now.

17:34 justin_smith: {blake}: for that, just throw the debug middleware in between each and every middleware

17:34 and have fun scrolling :)

17:35 in practice, it's usually a specific spot in the chain I am looking at, so I insert the debug middleware in that spot

17:35 {blake}: https://github.com/pjlegato/ring.middleware.logger

17:36 {blake}: Thanks. For some reason my local content is not having the content-type served. Which nobody cares about but IE.

17:37 justin_smith: {blake}: woah, this one looks pretty cool https://github.com/magnars/prone

17:38 {blake}: justin_smith: Woah, indeed.

17:39 justin_smith: also, .ninja domains are now available for $15

17:39 I hope clojure.ninja gets used for something awesome

17:42 TimMc: justin_smith: It won't, it will be recruiters.

17:42 justin_smith: :(

17:42 amalloy: rockstar.clojure.ninja the secret subdomain for the best candidates

17:42 justin_smith: haha

17:43 I hope that at least taco.cat ends up being something good

17:43 amalloy_afk_ninj: ugh c'mon irc, gimme a break

17:43 justin_smith: oh, taco.cat is already up, and it's a silly python program

17:43 tcrayford____: justin_smith: taco.cat is a friend of mine's domain haha

17:44 justin_smith: oh, nice

17:44 tcrayford____: was *weird* as hell seeing it here

17:44 {blake}: Did they just abandon the TLD system or something?

17:44 justin_smith: {blake}: massive expansion I guess

17:44 tcrayford____: it's a money grab haha

17:45 justin_smith: of course it is

17:45 {blake}: justin_smith: Well, good. I hated to see ninjas left out.

17:45 tcrayford____: lots of folk trying to get new TLDs that are interesting

17:45 TimMc: .cat is Catalan though, not one of the new TLDs

17:45 tcrayford____: I uh, don't think google take TLD into account like they do the actual domain though, for exact matches

17:45 yeah taco.cat is like 5 year sold

17:46 justin_smith: looks like clojure.sucks is not taken

17:46 but clojure.rocks is

17:46 {blake}: Ooh.

17:46 tcrayford____: another friend has "never.computer"

17:46 justin_smith: that's a good one

17:46 {blake}: "Clojure.sucks but it.sucks less than everything else."

17:46 tcrayford____: (or at least, he used to)

17:47 Ash: clojure.pizza

17:47 justin_smith: such.wow is available (and now I move this to #clojure-offtopic)

17:55 {blake}: Wow, putting in logger resulted in two dozen files being downloaded!

17:56 justin_smith: deps?

17:56 that's a lot for one middleware

17:56 AeroNotix: something something transitives

17:57 {blake}: https://gist.github.com/anonymous/0862bc4fadb769c89f84

17:59 justin_smith: ahh, of course, the logging libs

18:01 {blake}: It seems...excessive. That much code should fix your problem for you. =P

18:02 Heh. I love lein under Windows. "Terminate batch job (y/n)"...then whatever you type, terminate.

18:02 justin_smith: process management under windows in general is "fun"

18:03 {blake}: For the "Dwarf Fortress" definition of "fun".

18:03 justin_smith: does lein officially support windows now? at least at one point the attitude was that none of the lein devs used windows, and if it worked there it was basically a happy accident but not intentional

18:05 {blake}: justin_smith: Honestly? It's great under Windows. I don't know if it's officially supported or not, but I switch between Linux/Windows all the time, with no trouble.

18:07 justin_smith: that's cool

18:07 my info is likely out of date

18:09 {blake}: Honestly, having gone from Ruby to Clojure, I appreciate the crap out of lein. Although the last Ruby install I did was nice, with RVM.

18:10 justin_smith: (inc lein)

18:10 lazybot: ⇒ 4

18:10 tcrayford____: (inc lein)

18:10 lazybot: ⇒ 5

18:10 tcrayford____: you deserve more than that leinininininingen

18:11 {blake}: (inc lein)

18:11 lazybot: ⇒ 6

18:11 {blake}: (inc ALL-THE-LEINS!)

18:11 lazybot: ⇒ 1

18:11 TimMc: banananananagen

18:12 uptown: what's the sanest way to mock environment variables as in (with-environment-variables {"foo" "bar"} (fact "foo should be bar" (env :foo) => "bar))

18:13 (assuming midje and environ)

18:13 hiredman: the sanest way to do anything starts with not using midje

18:13 uptown: oh um

18:13 justin_smith: (inc hiredman)

18:13 lazybot: ⇒ 68

18:13 {blake}: uptown: Isn't the point of having environment variables not caring what's in them?

18:16 AeroNotix: environment variables do seem a weird thing to want to mock

18:21 uptown: what, then, should i

18:22 TimMc: AeroNotix: Uh, why?

18:22 You need to thread config into a program one way or another. Maybe I'm misunderstanding the midje question...

18:23 AeroNotix: TimMc: if your application's behaviour vastly changes with different environment variables, it's probably time to rethink.

18:23 TimMc: AeroNotix: I don't think that's a particularly unusual way to configure an app!

18:24 uptown: sorry, had a coffee accident here ha

18:24 AeroNotix: It's not, I'm just saying that needing to test each individual setting in tests seems like the envvars control too much

18:24 e.g.

18:24 DB_HOST=foo

18:24 is a good envvar


18:24 also good


18:25 bad envvar

18:25 namsayin?

18:25 uptown: DB_HOST might want a different value for testing purposes

18:25 DB_HOST=foo_test

18:25 AeroNotix: sure, and you set that before running the test stuite

18:26 DB_HOST=foo lein midje

18:26 run your test like that

18:26 uptown: in a repl, autotesting

18:26 if we agree that starting a repl is the way to go then okay

18:26 AeroNotix: I don't do that

18:26 but whatevs

18:28 TimMc: uptown: I don't think your tests should assume/test for any particular default for environment variables.

18:28 justin_smith: my typical pattern is to have a DEPLOYMENT variable in env, and then based on its value, load resources/config/development.clj or resources/config/staging.clj, resources/config/production.clj etc.

18:28 and you just decide at startup which is the right config file to load

18:28 actually .edn is better than clj, but whatever

18:29 oh, and also resources/config/testing.clj too

18:30 uptown: TimMc: I'm not really testing the value itself, i just want to mock it for downstream purposes

18:33 justin_smith: i'm trying to be 12factor compliant, which means trying to keep all the config in env

18:34 if env let me load a properties file programmatically just for test purposes i'd be happy that way

18:35 TimMc: uptown: So when your program goes out to get an env var, it demands that it be there? It can't fall back to a default?

18:35 justin_smith: uptown: looking at 12factor's website, you can use resources/config/x.edn as long as they are not checked into version control

18:35 AeroNotix: ugh, 12factor

18:35 justin_smith: uptown: and given that this is a security concern, you can also use an encrypted properties file

18:36 (with the key coming in from env of course)

18:39 uptown: TimMc: i'm wrapping a service that wants a config map so i'm just passing along whatever i find at the appropriate names, including nothing

18:39 the failure is handled

18:41 cbp: #join #clojure-offtopic

18:41 er

18:42 uptown: justin_smith: i was hoping to use env's property file support as the file-based solution, which works fine except for the testing build / teardown cycle

18:42 justin_smith: uptown: it wouldn't work to have a testing specific config?

18:43 Glenjamin: I normally put a thin layer between ENV vars and the app (eg. Config function/map)

18:43 Then just use a different one for tests

18:43 uptown: i can certainly get it to but was hoping to keep the codepath and resource count at zero beyond the test module

18:44 Glenjamin: Turning env vars into config values is an app init concern

18:45 Oh, that's basically what Tim said

18:45 mgaare: can also run whatever you want inside of a with-bindings on environ/env and merge in whatever you want to change from other things

18:46 uptown: aha that works. thanks all

18:47 say but if i can return to the previous topic: midje is evil?

18:47 what's the current flavor?

18:50 justin_smith: uptown: clojure.test, with the assistance of libs like expectations and test.check

18:51 that's the impression I get at least, I just use regular clojure.test

18:52 {blake}: Some people feel very strongly about midje, on both sides.

18:52 There are probably people who are very strongly ambivalent about it, too.

18:53 justin_smith: uptown: the problem I see with midje is that it seems in many ways to carry a specific strongly opinionated approach to how tests should be done, that doesn't neccessarily match the general philosophy or style of clojure itself

18:54 TimMc: uptown: I use midje. It is mostly nice, and when it isn't, I can fall back to building my own test utilities.

18:54 justin_smith: eg. in clojure.test the tests are functions, and I can define a function that calls test/is and call it from inside a test, it uses general functional programming concepts

18:55 uptown: i inherited some code that uses midje and just kept using it.

18:55 hm i'll keep an eye on that

18:55 thanks

18:59 TimMc: Midje locks you in a bit more but comes with a larger library of testing utilities.

19:03 {blake}: I've been using this logger at times (http://rjevans.net/post/2655430930/adding-custom-middleware-to-ring-compojure) to help me grasp compojure/ring/etc better.

19:04 And I notice, when I use it, only the user's request is logged, i.e., "myapp/whatever/page". Even if that page requests all kinds of resources.

19:05 At the same time, I note that I have middleware (rsrc/wrap-resource "/public") which I know is being used to serve resources.

19:05 I'm not getting how that's handled.

19:05 amalloy: your logging middleware must be applied inside of the wrap-resource handler insread of around it

19:06 change from (-> app (wrap-logging) (wrap-resources)) to (-> app (wrap-resources) (wrap-logging))

19:07 {blake}: I've been moving it up and down the chain.

19:08 I go to "/" and I see that request followed by the redirect to "/login"...

19:09 Wait...app vs....I'm doing "handler/api app"...

19:15 All my middleware: https://www.refheap.com/96607 and I still only see the main request, no resources, no AJAX.

19:36 notbrent: I feel like I would prefer if put/take macros for core.async were defined as >! and !< rather than the take being <! - I somehow still get tripped up on that

19:36 I believe that would be easier to visually parse

19:37 what do you folks think?

19:38 functions rather*

19:45 {blake}: Man, I hate it when I think I've figured out something, made it work, then can't make it break.

19:47 xyz_: Hello, I'm back. I made a lot of progress thanks to your help, but I need help with my conversion. Here is what I have so far : https://www.refheap.com/96610 . Any help ?

19:48 {blake}: xyz_: Are you trying to convert to a Number now?

19:49 xyz_: blake: well the first ones are broken as well and I can't seem to figure why. I have a "cannot be cast to clojure.lang.IFn" error

19:50 {blake}: desired-type

19:50 Wouldn't "(case (desired-type)..." cause "desired-type" to be executed as function?

19:50 xyz_: blake: hopefully it's just something silly, I'm still learning Clojure syntax

19:50 blake: oh maybe that's why. Let me try :)

19:51 blake: you are right it's getting better. I have a "No matching clause: class java.lang.Boolean", so it went further ^^

19:52 {blake}: There ya go.

19:52 xyz_: blake: I'm a bit ashamed now not to have found it... Thank you !

19:53 {blake}: xyz_: Heh. No worries. I'm a relative novice, too.

19:53 amalloy: xyz_: you can't really use a 'case to match on Class literals

19:54 because Boolean is really a symbol, not a class, and 'case doesn't evaluate its test clauses

19:54 xyz_: amalloy: I just saw that now by googling for my error : http://stackoverflow.com/questions/12028944/clojure-case-statement-with-classes

19:54 amalloy: does that seem correct to you ?

19:55 amalloy: yes

19:56 xyz_: amalloy: ok thanks. Time to learn about defmulti and defmethod then ^^

19:56 amalloy: i mean you can just replace (case x ...) with (condp = x ...) for a simple fix

19:57 xyz_: amalloy: oh intersting. I'll try that first then.

20:00 bodie_: notbrent, I think <! >! is clearer since the ! always comes after mutating functions, and the functions are < and >

20:00 notbrent: that makes perfect sense

20:00 thanks bodie_

20:00 bodie_: it is a little ugly though ;)

20:01 notbrent: indeed - I like with >! and !< how you can think of ! as a channel in the middle of two processes

20:01 one on the left puts it on, one on the right takes it off

20:01 but the convention of ! after mutating functions should take precedence there for consistency

20:01 unfortauntely

20:02 unfortunately*

20:02 bodie_: hello all -- I'd like to use a lein plugin from its latest upstream on github, rather than from clojars. how would I go about doing that?

20:03 I just want to put the dep in my project.clj as usual, and have it be usable by other members of my team. but it seems kinda un-kosher.

20:05 notbrent: also curious about bodie_'s question

20:05 amalloy: you can't run anything off of like "latest github commit"

20:05 it needs to be a jar somewhere in the world

20:05 you can jar it up yourself and publish it, if you want a particular version to be available

20:06 bodie_: hmm, ok. then how would I go about including it as a dependency?

20:09 notbrent: https://github.com/ato/clojars-web/wiki/About#do-i-have-to-use-leiningen-with-clojars-and-clojars-with-leiningen

20:09 in particular: https://github.com/technomancy/leiningen/blob/preview/doc/DEPLOY.md

20:09 {blake}: We use a local archiva server.

20:11 bodie_: notbrent, cool, thanks

20:12 notbrent: np

20:15 R0B_ROD: Hello

20:15 Currently exploring the Clojure Koans

20:21 n0n3such: moan

20:22 TEttinger: loan

20:22 n0n3such: loon

20:22 TEttinger: goon

20:22 n0n3such: bufoon

20:22 TEttinger: heh

20:22 n0n3such: lol

20:33 notbrent: (= ___ true)

20:42 dangit: I’m trying to use compojure with SS’s components. I can’t figure out how to get the component instance to the routes.

20:43 Can someone give me some guidance?

20:49 noonian: dangit: instead of using defroutes, write a function that takes the components it depends on as arguments and returns a call to compojure.core/routes with your routing code that depends on the component. Then in your server component or however you structure it (maybe have a RingHandler component) you call that function with any components it needs

20:49 zacts: huh, I think I may try the koans myself too

20:49 what do they teach mainly?

20:49 or are they just like euler problems?

20:51 noonian: i haven't really done them but I think they are designed to teach an understanding of Clojure more than figure out mathematical problems ala project euler

20:51 dangit: noonian: thanks, that’s helpful

20:51 zacts: oh neat

20:51 noonian: dangit: np :)

20:52 zacts: "By following along the path set before you, you will touch on all the major aspects of the language, from simple datatypes to macros, from tail recursion to Java interoperability. "

20:52 that's cool, I'll do them then

20:53 they are cooler than euler for what I want right now

21:06 doky: hello does anybody know why is problem when i sending emails in future throught (map #(send-email %) emails) ? when i send only in repl all emails are send correctly

21:19 justin_smith: doky: map is lazy

21:19 it won't do anything unless you consume the result

21:24 TEttinger: doky: the more correct way is with doseq, but you can also force a lazy seq with doall after using map

21:25 doky: justin_smith: i have cycle, do stuff then wait 2 seconds and repeat but when i try to sending email in that cycle and in one function i have (map #(send-email %) emails) it don't send anything ... but in lighttable when i call that function manually it works ... it took about 3 second to send email probably while it gain a connection

21:25 TEttinger: light table evaluates lazy sequences, just like the REPL will

21:25 but a running program won't

21:25 (doc doall)

21:25 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

21:25 TEttinger: (doc dorun)

21:25 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

21:26 justin_smith: TEttinger: better yet, dorun

21:26 yeah

21:27 doky: TEttinger: thanks doall works great :)

21:27 TEttinger++

21:28 justin_smith++

21:28 justin_smith: doky: it's a small difference for smaller collections, but in general dorun is the better choice if you don't need the return value

21:28 (inc TEttinger)

21:28 lazybot: ⇒ 38

21:28 doky: (inc TEttinger)

21:28 lazybot: ⇒ 39

21:28 doky: (inc justin_smith)

21:28 lazybot: ⇒ 175

21:29 doky: justin_smith: i forgot

21:34 zacts: hum.. I guess I'm stuck with JSON for now, as edn isn't really stable, and is subject to change

21:34 Unless you guys know of a better JSON alternative

21:36 justin_smith: zacts: I have had good luck with using cheshire for edn / json conversion

21:37 and also, edn hasn't really change much so far - though I guess there are no promises

21:38 but for the subset of edn that converts directly to json, I wouldn't expect changes (strings, numbers, vectors, hash maps)

21:38 TEttinger: (inc justin_smith)

21:38 lazybot: ⇒ 176

21:40 TEttinger: zacts: I like protocol buffers when I'm in .NET-land, but Kryo is very good at serializing Java stuff (and I think it works for Clojure too)

21:40 zacts: justin_smith: ah ok let me check out cheshire

21:40 justin_smith: huh, perhaps I may consider a subset of edn yeah

21:41 TEttinger: well serializing clojure is just having literal clojure expressions in a text file.

21:41 TEttinger: https://github.com/sritchie/carbonite

21:41 zacts: I mean clojure is basically already an AST

21:41 which is cool

21:41 justin_smith: zacts: also there is transit, if you want efficient transfer with json on the client end and clojure on the server end

21:41 TEttinger: right, but binary serialization is sometimes desirable (much smaller)

21:41 zacts: oh I didn't even consider that TEttinger

21:48 how about some good clojure general purpose parsing frameworks?

21:49 kind of like ANTLR

21:49 justin_smith: instaparse is popular

22:01 zacts: coolio

22:01 * zacts makes a new language to surpass C, Z

22:57 R0B_ROD: Seeking some basic introductory instructions on programming using Clojure.

22:57 ~book

22:57 clojurebot: book is http://www.pragprog.com/titles/shcloj/programming-clojure

22:57 R0B_ROD: Thanks and good evening to all.

23:14 AlwaysBCoding: what is a good way to cache an api response with a clojure/ring web app? i.e. if someone goes to a given route serve a static response for an hour then have the first response after the hour is up go through the controller get the new response and cache that? I’ve done this before w/ Rails, just wondering what library / workflow I should use to do it in Clojure?

23:17 fairuz: AlwaysBCoding: how about core.cache?

23:20 I would create a middleware to check for the request if there's a cache for it, and if it does, just send the cache instead

23:21 AlwaysBCoding: is there a good example anywhere of using core.cache with ring?

Logging service provided by n01se.net