#clojure logs

2015-01-28

00:09Jabberzthere 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?
00:10tomjackah, I see https://www.refheap.com/1e30c198d528300fcba9ef24a
00:10tomjackreification is exponential in depth?
00:11TEttingerJabberz: ##(str "Your mother was a hamster and your father smelt of elderberries, " "core.async")
00:11lazybot⇒ "Your mother was a hamster and your father smelt of elderberries, core.async"
00:11TEttinger...I have never used midje or core.async
00:15tomjackJabberz: would a mock channel behave differently from a normal channel?
00:16Jabberztomjack: 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
00:18Jabberzafaict, 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
00:20Jabberztomjack: 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
00:21tomjackyou want to check that some-data was put into _any_ channel?
00:22tomjackotherwise, 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
00:22Jabberzin midje terms, just that channel put was called with some args
00:23tomjackyou can check put! I think then
00:24JabberzI'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
00:26tomjackok, just check for clojure.core.async/put! ?
00:26tomjackdunno, good luck :)
01:01caternhttp://blog.venanti.us/ultra/
01:02catern>About two months ago I decided I'd been writing Clojure long enough that the time had come to optimize my development environment.
01:02caternweb devs should be banned :(
01:02caternfrom everything
01:02caternhipsteerrrrrrs
01:02catern(that is all)
01:04sharkzHi, how can I create a list '((10 20) (11 21)) from '(10 11) and '(20 21)
01:05sharkzI want to create a one-by-one pair of two equally-sized lists
01:05slipset,(list '(10 11) '(20 22))
01:05clojurebot((10 11) (20 22))
01:06slipset,(map list '(1 2) '(2 3))
01:06clojurebot((1 2) (2 3))
01:07sharkzthat's is cool
01:07sharkz*that's cool
01:07slipset:)
01:08sharkzI didn't know map can iterate multiple lists
01:08sharkzthank you so much :)
01:08slipsetNo problem!
01:08profilsharkz: map can: "(map f c1 c2 c3 & colls)"
01:09slipset~map
01:09clojurebotmap is *LAZY*
01:37Kneiva_,(mapv list '(10 11) '(20 21))
01:37clojurebot[(10 20) (11 21)]
01:37Kneiva_sharkz: isn't this what you wanted? --^
01:41teajoeHey 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
02:38clj123how 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]
02:40TEttingerclj123: ##(apply into [] [[1 2 3] [4 5 6] [7 8]])
02:40lazybotclojure.lang.ArityException: Wrong number of args (4) passed to: core/into
02:40TEttingerclj123: ##(into [] [[1 2 3] [4 5 6] [7 8]])
02:40lazybot⇒ [[1 2 3] [4 5 6] [7 8]]
02:40TEttingerdammit I can't remember
02:40havenwood,(vec (flatten [[1 2 3] [4 5 6] [7 8]]))
02:40clojurebot[1 2 3 4 5 ...]
02:40ucb,(apply concat [[1 2 3] [4 5 6] [7 8]])
02:40clojurebot(1 2 3 4 5 ...)
02:40TEttinger&(apply concat [[1 2 3] [4 5 6] [7 8]]) is correct, flatten is...
02:40lazybot⇒ (1 2 3 4 5 6 7 8)
02:41TEttinger~flatten
02:41clojurebotflatten 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.
02:41havenwoodinteresting
02:41havenwoodTEttinger: thanks, good to know!
02:41TEttingerhavenwood, I use flatten all the time, but only when I have total control of the data I am using
02:41TEttingerusually only for things I know are small and shallow
02:42clj123cool thanks
03:20muhukHi all.
03:20SagiCZ1morning..
03:25hellofunkzacts: those books look interesting, i'll check them out
03:33ianhedoesitSagiCZ1: it's 00:31!
03:33SagiCZ1ianhedoesit: ever heard of time zones?
03:33ianhedoesitno!
03:33SagiCZ1reminds me of some of my american friends
03:33ianhedoesitI live in a world where I reject the notion of timezones.
03:34hellofunkianhedoesit: and yet, you make a big deal out of the time
03:34SagiCZ1ianhedoesit: at least you don't deal with jet lags!
03:34hellofunk:0
03:34ianhedoesitI figure date time messes are too messy in the first place, even if I ignore timezones.
03:35ianhedoesitand my data is never more than a day off, so it's not really an issue.
03:35SagiCZ1ianhedoesit: i am fascinated by half our or quarter hour timezones.. that must really weird
03:35SagiCZ1*hour
03:36ianhedoesitSagiCZ1: I've never understood those. I haven't looked into why any place has those sorts of time zone variations though.
03:36SagiCZ1ianhedoesit: i think it's places that literally don't have any other interesting thing..
03:37daniel`sud afrika
03:37ianhedoesithttp://www.timeanddate.com/time/time-zones-interesting.html
03:38SagiCZ1i hope joda time knows about all these
03:38ianhedoesitthe first thing it talks about is India and why it has a 30 minute offset from UTC. actually kinda interesting.
03:40ianhedoesitneat, only two places in the world have quarter hour offsets!
03:40ianhedoesithow informative to the clojure community!
03:42hyPiRionSagiCZ1: yup, it does
03:42SagiCZ1hyPiRion: cool
03:51Glenjaminthe UK is the worst: if you forget to handle timezones your software still works 50% of the year
03:52hyPiRionIf you forget to handle time, it'll still work twice a day. etc
03:53Glenjamindo people have this problem in other timezones? I've only ever worked in GMT
03:54Glenjamin9/10 callsites convert to UTC - software only broken from march-october.
03:55hyPiRionThere is DST many places on earth
03:55Glenjaminright, but the non-dst zone isn't === UTC ?
03:56Glenjaminso if you're storing UTC, you'd notice if you miss one
03:56hyPiRionoh, sure thing. Ish
03:56winkGlenjamin: we're one off with CET - so glancing at logs it can be mistaken for UTC easily
03:56winkhyPiRion: are you goin to FOSDEM?
03:57clgvGlenjamin: I like the time zones with offsets of additional 30min or 45min
03:57winkI found http://qntm.org/abolish an interesting read
03:58hyPiRionwink: nope, unfortunately
03:58Glenjaminclgv: i would imagine anyone working in those zones gets good at time quite quickly
03:58Glenjamincertainly people working in those zones communicating times to people in other zones
04:14SagiCZ1Glenjamin: i dont think people in those timezones communicate with the outside world that much
04:15ianhedoesityeah, Nepal and New Zealand are pretty lonely.
04:44clgvSagiCZ1: australia? :P
04:44SagiCZ1clgv: they dont have full hour timezones?
04:44clgvSagiCZ1: check Darwin
04:44SagiCZ1clgv: oh nevermind then.. that's embarassing.. sorry :X
04:45clgvSagiCZ1: the other exotic ones are in southern asia
04:46clgvI'd never guessed that there are time zones with offset +13/+14
04:46cflemingHere in New Zealand we use a full hour offset, but we're still pretty lonely down here.
04:47Emppericfleming: sorry saying this from here, not from official channels but latest Cursive update broke debugging both in Mac and Windows
04:48SagiCZ1cfleming: do you kiwis get to visit Australia often? they seem pretty close but I imagine some people may never leave the island..
04:48EmpperiIdea 14
04:48cflemingEmpperi: Do you mean 0.1.44? 0.1.43 broke it, 0.1.44 should have fixed it
04:48Empperidunno, just the update Idea automatically told me to update :)
04:48cflemingSagiCZ1: Sure, Kiwis travel a lot
04:49Empperibut good to know
04:49SagiCZ1cfleming: cool//
04:49Empperiwill check that I have the latest version
04:49Empperimissing my debugger... :P
04:49cflemingEmpperi: 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
04:50cflemingEmpperi: I haven't forgotten about your action issue either BTW, just busy, sorry
04:50SagiCZ1cfleming: 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
04:50Emppericfleming: actually, I might have an idea what is causing it and it is not Cursive related
04:50Empperiit's about how Idea reads the keybindings
04:51Empperifor example, I have "load namespace into REPL" in keybinding ctrl+alt+l
04:51Empperiif I happen to press alt down before ctrl, or if I press them at the same time then it doesn't work
04:51cflemingSagiCZ1: That sounds weird, it should have a relatively straightforward linear history
04:51Empperiif I press ctrl down first, then alt and then l, then it works
04:51SagiCZ1cfleming: even when working across multiple REPLs? how should that work?
04:51Empperiannoying but should point to the fact, that the problem is *not* in Cursive
04:52Empperiand this problem is not there with Mac
04:53cflemingEmpperi: That sounds really weird - you're on Windows, right? Does this happen on a Mac too?
04:53cflemingEmpperi: Oh, no, ok
04:53EmpperiI use both and this happens only on Windows
04:53TEttingerEmpperi: try also binding alt-ctrl-l
04:53TEttingerif it distinguishes between ctrl-alt and alt-ctrl, maybe it's configurable
04:53Empperiwill do when I'm on pc again, right now doing work at home with my work laptop (mbp)
04:54TEttingerstill the strangest IDE quirk I've heard of in a while
04:54Empperiyeah
04:54Empperianyway I can live with that now that I know what is causing the problem
04:55EmpperiI was getting sick and tired of going to menu just to load the file into repl...
04:56cflemingEmpperi: Yeah, I bet. That sounds like a JDK issue to me.
04:56Emppericfleming: that doesn't happen on any other software, just with Idea
04:57cflemingSagiCZ1: The REPL history is partitioned by type, so local REPLs have a separate history from remote ones.
04:57Empperiand my keybindings for Cursive happened to bring it up
04:57cflemingSagiCZ1: 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
04:58cflemingSagiCZ1: But if you do "Show REPL history" it should show your recent history from the current REPL, definitely
04:59cflemingSagiCZ1: 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
04:59engblomI 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
05:22TMAengblom: it is an excercise for chinese remainder theorem and modular arithmetics -- you are not supposed to brute force the solution
05:25clgvengblom: as TMA says ;)
05:26clgvengblom: when you don't know about CRT you could at least restrict the search space by reasoning about divisibility of the numbers ;)
05:27tomjack(I'm 80% certain that) my problem was a perf bug in core.logic! :)
05:36tomjackI 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
05:39tomjackwhich is somewhat troublesome, because even in Agda I believe the state of the art for programs whose types verify their complexity is "semi-formal" :(
05:48Glenjaminanyone know why the "j" is clojure is italicised?
05:48engblomTMA: 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.
05:49engblomWhat I wanted to know if the coding style for brute forcing this problem is good, not how to solve it mathematically.
05:50engblomI 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.
06:00TMAGlenjamin: my take on that: 'tis some kind of reference to Java or JVM
06:02lachenmayerGlenjamin: to emphasise that clojure is not closure or clozure? ;)
06:03TMAengblom: as for the coding style [disclaimer: I come from common-lisp/scheme background] ... I would personally split the printing and computation into separate functions
06:06Glenjaminalways good advice imo ^
06:07engblomBut you would use list comprehension for brute forcing?
06:27clgvengblom: but the problem can be easily scaled such that the brute force attempt fails ;)
06:33TMAengblom: 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
06:33TMAengblom: also: no space before ) :)
06:40TMAengblom: (defn compute-solution [candidates] (for [i candidates ...] ...))
06:42engblomTMA: So you generate a list of canditates and then feed it to compute-solution?
06:43TMAengblom: not a list -- a lazy seq
06:44engblom(range) ?
06:44TMAengblom: in Common Lisp... (defun compute-solution (candidate-fn) (do ((i (candidate-fn) (candidate-fn)) ...) ...))
06:45TMAengblom: range produces a lazy seq, not list
06:45TMAengblom: in other words: yes
07:00H4nsjustin_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.
07:04TEttingerimagemagick is awesome though
07:04H4nsTEttinger: much awesomer than the java image stuff
07:06TEttingerhere, 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
07:06TEttingerif there are less than 11 colors, at least
07:06TEttingerwhich for PBM should be always
07:08arossouware there clojure forums, where i can ask skilled clojure coders to criticize my code?
07:08TEttingerarossouw: link to refheap or gist with your code and people will try here
07:08arossouwi see, thanks
07:08TEttingerthere probably are forums
07:09Glenjaminthere's codereview on stackexchange
07:09arossouwcool, thanks
07:09TEttinger(inc Glenjamin)
07:09lazybot⇒ 11
07:10arossouwi've tried something like this, not sure how to access outer block (#(take %1 %2) 3) '(1 2 3 4))
07:11justin_smitharossouw: there is a misplaced paren in there somewhere
07:11justin_smithwhat is that trying to do?
07:12justin_smith&(#(take %1 %2) 3 '(1 2 3 4))
07:12lazybot⇒ (1 2 3)
07:12Kneiva,((partial take 3) '(1 2 3 4))
07:12clojurebot(1 2 3)
07:12arossouwlets 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))
07:12justin_smitharossouw: again, you have an extra paren
07:12arossouwi see
07:12justin_smiththat doesn't even make sense
07:13arossouwok, i'll play around abit
07:13TEttinger(doc split)
07:13clojurebotHuh?
07:13TEttinger(doc split-at)
07:13clojurebot"([n coll]); Returns a vector of [(take n coll) (drop n coll)]"
07:13arossouw(= (__ 3) '(1 1 2))
07:13arossouw4clojure, dont want answer just hint
07:13arossouwwhere __ is function
07:14TEttingerfibs
07:14justin_smithoh yeah, that's definitely fibs
07:15arossouwso i should create an anonymous function that generates fibs and only print first 3?
07:16justin_smithnot print, return
07:16arossouwah, ok, thanks
07:16justin_smitharossouw: you need a function that takes a number n, and returns the first n fibs
07:19zactshelgikrs: http://mitpress.mit.edu/books/cognition-basic-musical-structures
07:25TEttingerfrom clojuredocs: ,((fn [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1))) 3)
07:25TEttinger,((fn [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1))) 3)
07:25clojurebot(1 1 2)
07:25arossouwcool
07:25arossouwi'll have to study lazy-seq, still new at that
07:25TEttingersee for yourself how to do it http://clojuredocs.org/clojure.core/lazy-seq
07:25TEttingerit's very powerful
07:26TEttinger,(defn fibonacci [n] (take n ((fn fib [a b] (cons a (lazy-seq (fib b (+ b a))))) 1 1)))
07:26clojurebot#'sandbox/fibonacci
07:26TEttinger,(fibonacci 30)
07:26clojurebot(1 1 2 3 5 ...)
07:26Glenjamini completely failed to write a function using lazy-seq in an interview this week :(
07:26TEttinger,(clojure.string/join " " (fibonacci 30))
07:27clojurebot"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"
07:27TEttingerGlenjamin, yeah I would have too
07:27arossouwit would crash if you did it recursively right? (with python)
07:27Glenjamini managed to write the loop..recur
07:27zactshellofunk: http://mitpress.mit.edu/books/ant-colony-optimization <- cool my next clojure project is going to utilize ideas from this
07:28Glenjaminbut then didn't look at the docs enough to write the lazy-seq, and got a bit tied up :(
07:28TEttingerarossouw, lazyseqs are often infinite. you only evaluate a finite portion by using take
07:28zactshelgikrs: sorry man, I meant that for hellofunk
07:28arossouwawesome
07:28justin_smitharossouw: yeah, if it were evaluated eagerly it would go into a loop until it ran out of stack space
07:28arossouwi think data scientists would love that
07:28justin_smitharossouw: 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
07:29justin_smitharossouw: and python does have something like that, it just has a more confusing way of using it
07:29arossouwso it releases memory on each iteration?
07:29TEttingerit keeps it around.
07:30TEttingerhowever java will garbage collect unused stuff
07:30justin_smithit actually uses more memory each iteration (but it can be released if you don't hold onto the beginning of the series)
07:30arossouwinteresting
07:31arossouwit would be cool if you could download a pdf of clojuredocs.org
07:31justin_smithlike 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
07:31justin_smitherr (nth (range) 1000000000) that is
07:32arossouwok, nth vs get ,which to choose?
07:32justin_smithget is for associative things
07:32justin_smithnth is for things that are ordered
07:32justin_smithvectors are both
07:32arossouwah
07:32justin_smithbut otherwise the choice is clear, because only one of the two makes sense
07:33justin_smithif a coll supports both get and nth, they are likely identical
07:34justin_smith(for that coll)
07:34justin_smithalso ##(nth [1 2] 22 :not-there)
07:34lazybot⇒ :not-there
07:34justin_smithnth takes an optional "not found" arg, like get does
07:35arossouwoh
07:38arossouwi think this might be a bit inefficient, https://gist.github.com/arossouw/2adb82ad208295be31a2
07:40justin_smitharossouw: one small thing - (complement nil?) is the same as some?
07:40arossouwpossibly, i'll try
07:40justin_smiththey are identical
07:40arossouwoh
07:40arossouwok
07:40arossouwthanks
07:40justin_smithI mean some? is the name of the function, the question mark is part of the name :)
07:41arossouwyeah, get it, seen that function
07:41justin_smithand (keep f coll) is the same as (filter some? (map f coll))
07:41TEttinger(remove nil? collection)
07:41justin_smithso you can just return (keep #(last (re-find re-imap-login %)) line)
07:41justin_smithand skip two let bindings
07:42arossouwnice
07:42justin_smiththat makes things more clear, but doesn't change the efficiency
07:42TEttingererr, one let binding justin_smith
07:43justin_smithTEttinger: it eliminates two, because the second is just the return value now :)
07:43TEttingerthe line with filter is outside the bindings
07:43justin_smitharossouw: also, (apply str (map (fn [x] str x "\n")) ...) could just be (clojure.string/join "\n" ...)
07:44arossouwawesome
07:44justin_smithTEttinger: yes, and I am replacing it with keep
07:44justin_smithTEttinger: oh, now I get it, never mind :)
07:44justin_smithyou are right
07:44TEttingerheehee
07:44justin_smithI was confused momentarily by the indentation
07:44TEttinger(inc justin_smith)
07:44lazybot⇒ 173
07:44TEttinger(inc indentation)
07:44lazybot⇒ 1
07:45justin_smitharossouw: in that case, the string/join will be faster than apply / str / map combo
07:46justin_smithsince you don't need to create the temporary lazy seq before making the string
07:49arossouwjustin_smith: how would i apply join "\n" to line-seq (io/reader file)?
07:49justin_smith,(clojure.string/join "," [1 2 3])
07:49clojurebot"1,2,3"
07:49arossouwah
07:49justin_smithjust make the line-seq the last arg to the join
07:52slipset,(apply str (interpose \, [1 2 3]))
07:52clojurebot"1,2,3"
07:52justin_smithslipset: that has the correct output, but string/join is always better
07:53slipsetmost probably true, but I'm somewhat fond of interpose :)
07:54TEttingerinterpose and interleave are both quite useful
07:55justin_smith(defn interject [e coll] (let [position (rand-int (count coll))] (concat (take position coll) [e] (drop position coll)))
07:55slipsetbesides, this is kind of cool
07:55slipset(apply str (interpose \, "123"))
07:56slipset,(apply str (interpose \, "123"))
07:56clojurebot"1,2,3"
07:56justin_smith,(clojure.string/join \, "123")
07:56clojurebot"1,2,3"
07:56arossouwhttps://gist.github.com/arossouw/2adb82ad208295be31a2 , looks slightly better now, thanks for the help
07:56slipset(inc justin_smith)
07:56lazybot⇒ 174
07:56slipsetdidn't know about that one :)
07:57justin_smitharossouw: don't forget you need (require '[clojure.string :refer [join]]) for that to work
07:57justin_smithor my preference, (require '[clojure.string :as string]) and change join to string/join
07:57arossouwok
07:57justin_smithalso, that map needs to be keep
07:58justin_smithotherwise you still get nils
07:58arossouwoh, cool, thought you ment like keep, like keep that part
07:59arossouwsee now, great stuff
07:59justin_smith,(keep next [[1] [12 13] [42] [5 7 9 11]])
07:59clojurebot((13) (7 9 11))
08:00arossouwso much to learn
08:00justin_smithif I had named keep, I likely would have called it winnow
08:00arossouwrefactored now :-) https://gist.github.com/arossouw/2adb82ad208295be31a2
08:00justin_smith(getting rid of the husks :))
08:02arossouwanyone here using http-kit with nginx in production?
08:02justin_smithyes
08:02justin_smithnot via the plugin though
08:02arossouwdo you have to lein uberjar everytime you submit your code?
08:02justin_smithyes
08:02arossouwjustin_smith: do you use midje to test the stuff or deftest?
08:03justin_smithclojure.test (deftest)
08:03arossouwok
08:03arossouwhows the performance sofar?
08:03justin_smithit's been excellent
08:03arossouwof nginx + httpkit
08:03justin_smithhaven't had to scale beyond one server yet
08:03arossouwinteresting
08:04arossouwplanning on rewriting python web app to http-kit + compojure + nginx
08:04justin_smithcool
08:04arossouwdon't like orm's for some reason
08:04justin_smiththat's a smart thing to dislike
08:04arossouwlol
08:05arossouwis clojure gaining market share?
08:06justin_smithI think so, yes
08:06justin_smiththough being a lisp, I don't know how big a market share it can reach
08:07arossouwdoes lisp have a bad reputation?
08:07justin_smithit doesn't look like math the way you learn it in highschool
08:07tbaldridgearossouw: no, it just requires you to think a bit more before you start to code
08:07justin_smithpeople are reluctant to learn the syntax
08:08tbaldridgearossouw: with great power comes great responsibility
08:08arossouwi see, its unfamiliour to most and people usually prefer to stick to known stuff
08:08arossouwi'm afraid i can't like any other programming language now
08:09justin_smithyeah, 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)
08:09justin_smithhehe
08:10justin_smithafter 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
08:10arossouwdo you think it might persaude people if you give a clear overview of the benefits of functional coding?
08:10justin_smith(OCaml, sml, haskell maybe)
08:10justin_smitharossouw: 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)
08:10arossouwtried haskell, will try again, tricky to learn
08:11justin_smithyeah, haskell is a challenging language
08:11justin_smithbut it's worth knowing at least one ml and at least one lisp, imho
08:11arossouwok
08:12justin_smithbut yeah, I think one thing at a time, and the best way to convince anything is cool is to make something awesome
08:12arossouwtext parsing is slow in haskell, but i guess i'd need more experience
08:12justin_smithhaskell has multiple string types, and the default string type is very inefficient
08:13arossouwok
08:13tbaldridgeand 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)
08:13muhukif you're interested in haskell but don't want to leave JVM world; try frege
08:13justin_smithtbaldridge: yeah, F# is a good one (it's heavily derived from OCaml, my favorite ml)
08:14tbaldridgeI started playing with ML awhile back, but was put off by how bad the library support was. That's mostly fixed by F#
08:14luxbocktbaldridge: when's your next video coming out? I haven't seen any new ones in a while
08:15arossouwmuhuk: i'll check it out, thanks
08:15tbaldridgeluxbock: today or tomorrow, I've hit a bit of a writer's block, going to get back into it
08:15luxbocktbaldridge: cool. I really like your transducer ones
08:29dysfunwhat's the clojurescript idiom for when you need to initialise a component through a browser API that takes a function?
08:29dysfune.g. getUserMedia(function() {})
08:30Glenjaminpass it a fn
08:30dysfuncurrently i've got it putting onto a core.async channel
08:30Glenjaminoh right, i see what you mean
08:30dysfuni'm trying to get it *out* of callback mess :)
08:31dysfuni'm using it with om
08:36Glenjaminyou could probably wrap up the idiom into a channel that's immediately dereffed?
08:38dysfunyeah, it's looking like that's the way
08:39dysfundoesn't seem the cleanest, but it has the benefit of being straightforward
08:39clgv"wrap up the idiom"?
08:41dysfunyeah, once i've got it working, i'll see how to tidy it up
08:53arossouwis it possible to create a popup calandar with clojurescript?
08:53R0B_RODarossouw: Its possible to do many things with clojurescript
08:53arossouwoh, ok
08:54R0B_RODarossouw: If you layout your problem definition and design a simple algorithm Im sure you will be able to code what you want.
08:54arossouwi see
08:55R0B_RODarossouw: I say it as theory since I have no experience with coljurescript or clojure.
08:55R0B_ROD+ I mistype all the time
08:56justin_smitharossouw: clojurescript has full access to javascript
08:56clgvarossouw: you can narrow it down to "is X possible with JavaScript & HTML?"
08:57justin_smitharossouw: so you can use whatever javascript libraries are apropriate (and there are calender libs for javascript)
08:57michaelr525hi
09:00arossouwok, thanks
09:02michaelr525hmm
09:02Glenjaminclgv: i should really have said "define a function"
09:02michaelr525I need to do this in Clojure: new GenericType<ChunkedInput<String>>() {}
09:02michaelr525any idea?
09:03michaelr525it's from here: https://jersey.java.net/documentation/latest/async.html#d0e10298
09:03justin_smithmichaelr525: generics don't exist in the jvm
09:03justin_smiththey only exist in the java compiler, which we are not using
09:03justin_smithignore the generic part, and just make a ChunkedInput
09:03michaelr525justin_smith: I'm not sure it's going to work in this case..
09:04hyPiRionjustin_smith: GenericType, rather.
09:04justin_smithhyPiRion: oh, right, thanks :)
09:04michaelr525justin_smith: that code expects to have that type information in runtime..
09:04hyPiRionbut this is some anonymous class magic instantiation
09:04justin_smithmichaelr525: generics are not enforced by the vm, in fact they don't even exist
09:04justin_smithhyPiRion: so that calls for reify, right?
09:05hyPiRionjustin_smith: right
09:05michaelr525err..
09:05michaelr525from 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."
09:06michaelr525that's why I don't think it would work ;)
09:08justin_smithmichaelr525: what that means is that an instance of GenericType is provided as an argument to redEntity
09:08justin_smithas hyPiRion said, use reify to create that instance as the first arg to readEntity
09:08justin_smithGenericType is what is important here, the generics are just noise
09:10justin_smithreify (and sometimes proxy) are how we create anonymous class instances like in that code snippet
09:10zactshi clojurists
09:11R0B_RODHello justin_smith
09:11justin_smithhello
09:11michaelr525justin_smith: ok, thanks.. i'll give it a try before wraping that in a java class..
09:12michaelr525i'd have to override some of GenerType's methods to return the parametrized type name at runtime
09:12justin_smithmichaelr525: yes, reify is capable of doing that
09:13zactsI feel like my designs in clojure are lacking
09:13zactsI want to gain more experience
09:13zactswith functional programming
09:13justin_smithzacts: you should make something
09:14zactswhat to make? :-)
09:14TMAzacts: almost anything, really
09:14zactsI feel like I know how the pieces move in chess, but don't know how to play the game
09:14zactswell
09:15slipsetzacts: if you have a working webapp, implement either the front-end or the back-end in clojure(script)
09:15slipsetIf you work in a company which uses irc/slack/hipchat or something, implement a simple bot which looks up jira issues for you
09:16justin_smithor, 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)
09:16zactshum.. nah I don't want to do chess right now
09:16zactsit was a metaphor for my clojure understanding
09:16zactsI guess I may just start with the music ideas
09:16TMAzacts: I have found that at least for me the main point was to change the thinking. the designs then came spontaneously
09:17zactsI like this book on ants too though
09:17zactshttp://mitpress.mit.edu/books/ant-colony-optimization
09:17slipsetIMHO, 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.
09:17zactsmaybe I could make an ant simulator
09:17justin_smithzacts: 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
09:17augustlis there something like datomic's squuid available as a stand alone lib?
09:18justin_smithzacts: one of Rich Hickeys fist big demos of clojure concurrency was an ant simulator
09:18zactsoh really? coolio
09:18dnolenClojureScript 0.0-2740 released, bunch of Windows fixes
09:18justin_smithaugustl: iirc there is an under-documented method in java.util.UUID for generating SQUUIDs
09:19slipsethttps://gist.github.com/spacemanaki/1093917
09:19slipsetant-demo
09:19tbaldridgezacts: video of the ant-demo is in the last 30 min of this video: https://www.youtube.com/watch?v=dGVqrGmwOAw
09:19zactsoh nice! I'll check it out
09:20justin_smithzacts: make your own ants demo and then look at all the ways it is inferior to the one Rich Hickey mad :)
09:20augustljustin_smith: ah, will see what I can find :)
09:21justin_smithaugustl: I think the key is how one constructs the mostSigBits and leastSigBits to the constructor
09:21zactslol justin_smith
09:22Glenjaminthat is a looong video
09:24augustl`new UUID(new Date().getTime(), new SecureRandom().nextLong())` seems to work
09:24justin_smithcool, didn't realize it would be that simple, but makes sense I guess
09:25augustlit's different from the one in datomic though
09:25justin_smithand that returns the right .timestamp value?
09:25augustlI get 0000014b-30eb-c56a-cba6-ff9a806cbef0, 0000014b-30eb-c56b-eacf-04128f2c0e06, etc
09:25augustlthere are fewer zeroes in the one from datomic, fwiw
09:26augustls/zeroes/leading zeroes/
09:27clgvzacts: I am implementing ACO algorithms in Clojure ;)
09:27justin_smith,(.timestamp (UUID. (.getTime (java.util.Date.)) (.nextLong (java.security.SecureRandom.)))
09:27clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
09:29justin_smithaugustl: another thing is that it doesn't actually create a time-based UUID (I don't know if that matters to you or not)
09:29justin_smith,(.timestamp (java.util.UUID. (.getTime (java.util.Date.)) (.nextLong (java.security.SecureRandom.))))
09:29clojurebot#<UnsupportedOperationException java.lang.UnsupportedOperationException: Not a time-based UUID>
09:32zactsclgv: oh nice
09:32zactsclgv: perhaps I'll hang out with you here then
09:33zactsso hellofunk for music, clgv for ACO ants project =)
09:33zacts#clojure is really a cool channel so far with really smart people
09:41samiswellcoolzacts: agreed
09:46michaelr525reify only supports interfaces hmm
09:46michaelr525maybe proxy instead..
09:49donbonifaciohum.. 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
09:54justin_smithdonbonifacio: are you associating new keys that aren't part of the record, or dissociating keys that are part of the record?
09:54donbonifacionop, they are totally constant, and only read data
09:55donbonifacioI store them all (about 30 objects)
09:55donbonifacioand then just read info from them
09:57michaelr525justin_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) ?
09:58justin_smithhttp://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
09:59justin_smithso you need a named type, that can be referred to statically from java that extends an existing base class?
09:59justin_smithaccording to cemerick's page that means you need gen-class, which is too bad
10:00michaelr525it doesn't have to be a named class..
10:00michaelr525I just need an instance of that classs
10:00justin_smithin that case proxy should work, if you can figure out how to override the default constructor?
10:01michaelr525i'll dig deeper ;)
10:04zarkoneHello 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:05zarkoneboth for Chrome and FF
10:13michaelr525no
10:13michaelr525doesn't seem like proxy can do it..
10:13michaelr525damn
10:22justin_smith,(.newInstance (class (proxy [Object] [] (toString [] "silly"))))
10:22clojurebot#<Object$ff19274a sandbox.proxy$java.lang.Object$ff19274a@4bb1e2ee>
10:22justin_smithgiven a proxy, you can get its class and invoke the zero argument constructor
10:23stuartsierraaugustl: Time-based "Version 1" UUIDs don't put the most significant time bits first.
10:24stuartsierraDatomic squuids follow the format of random "Version 4" UUIDs but with the leading bits as time.
10:28augustlstuartsierra: ah, good to know, will look into that
10:29clgvzacts: hehe
10:44michaelr525justin_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:46justin_smithmichaelr525: how did you go about implementing the constructor?
10:46zactshum.. clgv what kinds of applications are you working on with ACO?
10:47zacts(if I may ask)
10:53dysfunhrm, how do i use libraries that don't use cljx from clojurescript if crossovers are deprecated?
10:53dysfunin this case, i want to use flatland/useful
10:55dysfuni know that the module i require doesn't do anything that clojurescript doesn't support
11:09clgvzacts: the classical ones - combinatorial optimization
11:09zactsoh neato
11:49denikUsing, test.check, is it possible to generate hash-maps with matching, unique properties (e.g. ids)?
11:50denikTwo maps should share the same val at k
11:50cemerickdenik: yes; see `bind` in its API
11:50denikok
11:50reiddraperdenik: use gen/fmap to add that key after generating the two values
11:51cemerickor that :-P
11:51denikwhat do you mean by two values
11:51denikit would be a shared value
11:51denika pool of unique ids, for example
11:51Glenjamin(gen/fmap #(assoc % :k2 (:k1 %)) your-generator)
11:52Glenjaminoh, i thought you wanted one hash-map with two values the same
11:52Glenjaminwell, the general idea is the same anyway
11:52denikokay, I'll try to figure it out
11:52dweavewhat does * mean around symbol names ie: *my-symbol*
11:52denikthanks everyone :)
11:53Glenjaminreiddraper: while you're here - if i want a number > or < some constraint, am i better off using choose, or gen/fmap with int?
11:53reiddraperdenik: 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:53reiddraperGlenjamin: probably choose
11:54denikreiddraper: copy that
11:54Glenjaminreiddraper: thanks - it's been super easy to far to expose stuff to JS
11:54nic77so guys im havin some trouble with graph theory i think
11:54reiddraperGlenjamin: happy to hear that :)
11:55Glenjamini'm interested to try and put individual generators into npm modules somehow - like test.chuck but more granular
11:55nic77the wikipedia doesnt really explain the explanations lol i think im missing some building blocks
11:56Glenjaminalthough download size isn't really a constraint, being able to mix&match and move versions easily is pretty useful
11:58nic77these vertex and nodes and edges, whats with all of that
11:58nic77im not imagining something correctly
11:59nic77i thought it was a graphics thing
12:00nic77ill piece it together
12:00nic77this sucks though, its not clicking like things usually do
12:03SagiCZ1oh.. i was like.. this channel fell awfuly quiet today.. and then i noticed my scrollbar is stuck
12:03nic77http://en.wikipedia.org/wiki/Vertex_%28graph_theory%29
12:03nic77hey sag
12:03nic77yeah its gonna get sad here in a min
12:03SagiCZ1nic77: how come?
12:04nic77so that wiki link makes graph theory seem more like a venn diagram with arbitrary
12:04nic77im just a n00b with weak math thats why sag
12:04nic77but theres something about it i do understand, how to use it
12:04SagiCZ1nic77: that wouldnt sadden me
12:04nic77once i limp along
12:05nic77then i was projecting, giving
12:05nic77heck ill be back, have to tend to some animals
12:06nic77and turbotax
12:06SagiCZ1nic77: dont pay taxes to your turtle and feed the state some salad
12:07nic77hmm, is that a phrase i dont know of?
12:07nic77has a ring to it
12:07SagiCZ1nic77: no i just made that up, sorry
12:07nic77never heard that :D
12:07nic77well im in, good one
12:08nic77turtles would be easier tbh
12:08nic77were talkin old english mastiffs
12:08nic77im all for a high priced turtle bloodline
12:08nic77with registration papers
12:09nic77probably galapagos
12:09nic77hardly enough to start a registry though
12:09SagiCZ1nic77: ;)
12:09nic77id get into that biz
12:10nic77maybe
12:10nic77i dunno, depends on if it would end up animal smuggeling
12:10nic77or if it ends at uncle bills
12:10nic77thats how you know your into something one step above drugs
12:10nic77when product arrives at uncle bills
12:11nic772 years ago in ohio next to me a wild animal refuge place had nearly all of its animals set loose
12:12SagiCZ1nic77: how many did you catch_
12:12SagiCZ1?
12:12nic77none im in indiana
12:12nic77its just related a bit
12:12nic77like in one of those graphs
12:14nic77the laws and stigma with having tigers and crap, the dark element and shady dealings
12:14nic77that lead to lawsuits and crap
12:15nic77county and state came down on the guy so he turned them loose and i think killed himself
12:15nic77its a bad industry like the drugs, comes with alot of baggage
12:17nic77like stolen art or something that comes along with opposing armys/ideals
12:17nic77but 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:17nic77i dont think they killed any animals but did have to round them up
12:17nic77it took a few days, maybe even a few fews
12:17nic77big cats and stuff
12:18nic77lion on the highway, bears even tigers oh my
12:18arrdem#clojure-offtopic please <3
12:19clgvarrdem: do you think the bot will follow those orders?
12:20arrdemclgv: I wasn't paying enough attention to decide it's a bot :P
12:20arrdemjust glanced over and saw a couple paragraphs of offtopiuc
12:20clgvarrdem: either a bot or a child ;)
12:20nic77around here a guy used to have a refuge, ran IMI irving materials
12:20nic77he got sued for capping the market and scaming extortion crap
12:20nic77concrete guys :D
12:20nic77they are just how they seem in the movies it seems
12:20nic77a guy in new york bought a dog from us and is currently slandering, hes a concrete bull too
12:20nic77is attempting to slander and blackball us currently
12:20nic77so becarefull when you mention turtles
12:20arrdemoh good.
12:20nic77hah, a bit of both
12:20nic77sorry guys
12:20arrdemamalloy_: fingerguns please. nic77.
12:20nic77what?
12:20clojurebotwhat is not a bug
12:23Mr0was that me? im having a keyboard issue at the moment
12:24justin_smithnic77: we have an off topic channel, please don't fill up this channel with off-topic stuff
12:24justin_smithwe have a separate off-topic channel, that is
12:25nic77started out on topic just so you know
12:25nic77:D
12:27nic77motives are easy for some
12:27nic77i do want to know about the graph theory question
13:10{blake}What is "com.s
13:10{blake}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{blake}(Or at least, Google turned up nothing I could understand.)
13:11justin_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:14tehgeekmeisteris there a core clojure thing or idiom for applying a bunch of functions to one collection?
13:14H4nsi'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:14H4nsis 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:15tehgeekmeister{blake}: i want to apply them independently, not sequenced
13:15justin_smithH4ns: I tend to be pretty conservative about using or updating libs
13:17Glenjamintehgeekmeister: you mean like ##(->> [1 2 3] (map inc) (map #(/ 2 %))) ?
13:17lazybot⇒ (1 2/3 1/2)
13:17H4nsjustin_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:18justin_smithH4ns: 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:18Glenjaminjustin_smith: security updates, cascading upgrades
13:19Glenjaminlarger change when you do finally upgrade being harder than many incremental changes
13:19Glenjamindependency management is generally just hard
13:19justin_smithGlenjamin: fair enough. My security mostly rests on nginx and ssl.
13:19justin_smithsure, that's true
13:19tehgeekmeister{blake}: no, one set of functions, one collection. apply each function, and return a seq of the results
13:19Glenjaminif ring had a security vuln, you'd patch nginx to block the attack vector?
13:20H4nswe'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:20Glenjamintehgeekmeister: something like ##(map apply [inc dec] (constantly 1))
13:20lazybotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$constantly$fn__4178
13:20justin_smithGlenjamin: 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:20H4nsnot sure if that is a great idea, but it sure sounds better than endless exclusions lists
13:21Glenjamintehgeekmeister: sorry: ##(map apply [inc dec] (repeat 1))
13:21lazybotjava.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long
13:21Glenjamindammit, repl hates me today
13:21Glenjaminoh, i see why that doesn't work
13:21Glenjaminanyway, the general idea would be to map function application over the list of functions
13:22justin_smithGlenjamin: 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:22justin_smithnot that we can always count on backports if we are stuck on an old version of course
13:23H4nsjustin_smith: like i said, you're shifting the cost to later.
13:23Glenjaminthe cascading updates problem is more common i reckon
13:23Glenjaminyou need feature X from lib A, causing the whole tree to be invalid
13:24justin_smithH4ns: 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:24Glenjamin{blake}: what makes you say that?
13:25Glenjaminjustin_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{blake}Ruby, in particular, is like a kid with ADD.
13:25tehgeekmeisterGlenjamin: ah, that makes sense
13:25tehgeekmeisterGlenjamin: getting back into the functional mindset still
13:25justin_smithGlenjamin: immutability actually has some nice consequences regarding security holes, actually.
13:26Glenjaminit's just that there's a relatively small number of libraries, and the maintainers are still using them
13:26Glenjamingive it another 5 years of dependency fragmentation
13:26{blake}Everything is deeply intertwingled. And minor revisions tend to invalidate reams of code.
13:26justin_smithand immutable data structures (at least their pervasiveness), is definitely a property of clojure
13:26Glenjamincould 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{blake}I love the way Noir split itself, e.g.
13:28justin_smithGlenjamin: also in terms of upgradability, idiomatic clojure code tends to be coded against interfaces and not concrete types, which tends to reduce brittleness.
13:29justin_smithbut yes, dependency management can be a pain in the ass, even in clojure
13:29Glenjamindo protocols have to do complete implementations?
13:29justin_smithnot at all
13:29Glenjaminthat's a big +1 for this then
13:29Glenjaminnew interface method doesn't break existing users
13:29justin_smithright
13:30justin_smithin pure clojure (not using java), interfaces don't even need complete implementations
13:30Glenjaminoh? i thought you had to declare all methods?
13:30justin_smithnot from clojure, no
13:31llasramWelllll, but unimplemented protocol methods will throw an exception
13:31llasramSo it isn't that useful a feature (IMHO)
13:31justin_smithllasram: if you call them
13:31justin_smithllasram: we are talking about libs breaking because a spec changed
13:31llasramAh,
13:31llasramnm
13:31llasramApologies for not reading full context before jumping in
13:32H4nsi think the basic problem is that one cannot express imprecise dependencies in leiningen
13:32H4ns(or maven, ftm)
13:32justin_smithGlenjamin: 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:32Glenjamini think its relatively accurate at the moment
13:32Glenjaminbut not because of anything that's a property of the platform
13:32justin_smithbut 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:33Glenjaminhttps://groups.google.com/forum/#!topic/clojure/WuS31RSiz_A
13:33Glenjamin"Dependencies suck, so stop sharing code please"
13:33Glenjaminto tl;dr it somewhat uncharacteristically
13:34perplexaheya
13:35perplexai 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:36perplexamy 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:36perplexaand tips where to start? ;/
13:36Glenjaminanyway, the above problem is why i keep thinking about writing a package manager for utility functions
13:38tbaldridgeperplexa: 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:39tbaldridgeyou gain two things a) more extensible code, b) less reliance on wacky macros like providing
13:39tbaldridge*provided
13:39perplexahmyeah the code is bad ;p
13:40perplexamy 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:43perplexawas 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:43perplexa... 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:44perplexathe class not found exception magically disappeared after down and upgrading clj-time, though ;/
13:44justin_smithperplexa: maybe you had some stale compiled artifacts that didn't get cleaned properly?
13:45perplexajustin_smith: lein clean should do the trick, though?
13:45justin_smithyeah
13:46justin_smithyou could run lein deps :tree to verify you are seeing the version you expect pulled in
13:49perplexajustin_smith: that looks horrible
13:49perplexahadoop ftl ;<
13:49zactshellofunk: yo man
13:50hellofunk zacts: 'sup dude
13:50zactshey, so what do you think about those computer music books?
13:50justin_smithperplexa: bad dep tree?
13:51hellofunkamalloy_: 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:52hellofunkamalloy_: 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:53perplexajustin_smith: tells me about lots of exclusions that i should consider
13:54dnolenFacebook announced React Native - target Android & iOS w/ JS - too bad ClojureScript isn't on board yet w/ React ;)
13:54justin_smithhellofunk: if you cons, the first value you add ends up at the end
13:54justin_smith,(reduce cons () (range 10))
13:54clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>
13:54justin_smith,(reduce #(cons %2 %) () (range 10))
13:54clojurebot(9 8 7 6 5 ...)
13:55justin_smithor is that a non-sequitor?
13:55hellofunk,(reduce #(cons %2 %) [] (range 10))
13:55clojurebot(9 8 7 6 5 ...)
13:55arrdemhellofunk: conj
13:56arrdemfast append fts
13:56arrdem*ftw
13:56justin_smitharrdem: I was making a point about cons / fold
13:56justin_smithit would have been simpler code, but less clear a point, if I used conj
13:57hellofunkjustin_smith: but reduce in clojure is a foldl so not sure you can really get the proper operation expressed
13:57arrdemjustin_smith: understood. my read of hellofunk's last was that s?he was trying to show the appending behavior.
13:57justin_smithahh, rightr
13:58dino-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:58hellofunkfor 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:59hellofunkthat's the suggestion from the wikipedia diagram, but perhaps i am interpreting it wrong
14:00hellofunk(actually i meant the first 2 would be 0 + 1)
14:00justin_smithhellofunk: 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:00hellofunkjustin_smith: well, that is indeed the question i'm asking
14:01justin_smithhellofunk: at least in haskell, order of execution is undefined unless you explicitly use something like a monad that enforces ordering
14:01justin_smithI don't know how far we can generalize that though
14:01hellofunkjustin_smith: checkout these two diagrams for foldl and foldr http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29
14:03hellofunkjustin_smith: based on these, what would you say are the first two args to a foldr of + over (range 5)
14:04dino-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:06justin_smithhellofunk: 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:07hellofunkjustin_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:09justin_smithwhen I read that diagram, foldr preserves order
14:09justin_smithalso, I think foldl and foldr are terrible names that makes it much too easy to accidentally swap them
14:09justin_smithand I would have named them fold and dlof if I invented them
14:10justin_smithhellofunk: oh, wait, the operation is cons, so yes, reversing once and then reducing with cons would preserve order
14:10justin_smithsorry
14:10hellofunkit'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:10justin_smithdouble reverse
14:12justin_smithhellofunk: how did laziness come into play here again?
14:13hellofunkjustin_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:14justin_smithhellofunk: 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:14justin_smiththese give you opposite effective orderings
14:14justin_smithspecifically for the collection building (which can be lazy / non-lazy)
14:15hellofunkjustin_smith: actually i just saw that laziness is discussed about halfway down that wiki page
14:16hiredmanlaziness 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:17hiredmanin clojure + is not lazy, and numbers are not lazy, so a fold that produces a number cannot be lazy
14:17Glenjamindnolen: do you think cljs would be able to target React Native?
14:18hellofunkjustin_smith: those diagrams don't really do much to clarify the issue, and in fact i think lead to more confusion
14:19hellofunkhiredman: 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:19hiredmanhellofunk: that is a bad structure to try and understand with
14:20hiredmanhellofunk: the order of the reduction doesn't matter in that structure
14:21justin_smithhellofunk: 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:21justin_smithwhether that tree is an evaluation tree or a literal tree (because your function was a collection building one)
14:22justin_smithhellofunk: 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:23justin_smithalso, if you wanted a reducing function, - may be a better example, since order matters with -
14:24hellofunkgood point
14:24hiredmanthe 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:25justin_smithexactly
14:25hellofunki see, so thinking of these examples with cons in mind is the best way to visualize
14:27hiredmanif 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:27hellofunkhiredman: that's helpful
14:28hiredmanthe 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:28justin_smithhiredman: wait, wouldn't a right fold consume the leftmost element of the sequence first?
14:28hellofunkjustin_smith: actuall the wiki diagram lines up with the hiredman example, i think it's clicking with me
14:28hiredmanthe left fold has to descend the entire structure in order to return the first result
14:28justin_smithoh, never mind, that's what you said
14:29justin_smithI just misread what he was saying
14:29hellofunkhiredman: that's actually quite illuminating, thanks
14:42amalloyanother 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:43amalloybut 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:48hellofunkamalloy: 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:50amalloyhellofunk: but you can't, because there are no lazy data structures in use there
14:50hellofunkamalloy: so is the burden for laziness on the data or on the function? ie the consumer or that which is consumed?
14:50amalloythe language
14:51amalloyclojure's evaluation semantics are eager, so no foldl can ever be lazy
14:51amalloy(no foldr either)
14:51hellofunkamalloy: is not a lazy foldl possible in clojure, maybe not with reduce?
14:51stuartsierrareductions!
14:52amalloywell, kinda
14:52justin_smithI 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:52amalloyreductions 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:52stuartsierranot the same as foldl, but gives you a sequence of "intermediate" reduce results.
14:53hellofunki'm familiar with reductions but it seems like a cheat in the theory of folding
14:53felixfloresdoes anyone know how to insert a record's default values using korma?
14:53gfrederi`reduce can do that via reduced though, right?
14:54aaelonyI 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:54felixfloresI tried something like (insert article (values {}))
14:54felixfloresit doesn't work
14:54amalloygfrederi`: yes. that's the one i think of as a cheat, though
14:54hellofunkgfrederi`: 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:55hellofunki would probably greatly benefit from studying haskell for awhile
14:56gfrederi`oh okay I didn't know we had ruled out cheating
14:57justin_smith"#clojure: oh, okay, I didn't know we had ruled out cheating"
14:57hellofunkgfrederi`: for example, i don't think haskell requires the notion of either "reductions" or "reduced" to achieve these basic features of lazy folding
14:57justin_smithgfrederi`: makes a nice tagline I think
14:57aaelonyah... looks like the develop branch is at 1.9.1-SNAPSHOT level ... (nevermind)
14:58xyz_Hello, can someone help me iterating over a nested map and pass the path (ie. the [:key1 :key2]) to my mapping function ?
14:59amalloygfrederi` sounds like an italian name. signior frederi
14:59justin_smithxyz_: so you want to get to every nested value of a map, and get the path to that thing from the root?
15:00hellofunkjustin_smith: even if that' not xyz_ 's question, it's one i'd be curious about
15:00xyz_@justin_smith exactly
15:01amalloyhttp://stackoverflow.com/a/21769786/625403
15:01xyz_the function should receive the key, value and path (but the path could be enough, right ?)
15:01amalloyjust needs a slight modification to use the vals as well as the keys
15:02amalloyor take what's there and map get-in over it
15:02justin_smith(inc amalloy)
15:02lazybot⇒ 217
15:02justin_smiththat's awesome
15:02dino-I'm very new. A little confusing you can't use nil in place of '()
15:03justin_smith(inc puredanger) ; for writing it
15:03lazybot⇒ 31
15:03dino-I guess it doesn't mean "the empty list"
15:03xyz_@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:03justin_smithdino-: () is an empty collection, nil is the null pointer
15:03justin_smithdino-: in many languages, a null pointer means "empty list", this is not one of those
15:04dino-justin_smith: thank you
15:04justin_smithdino-: the function seq will give you nil for an empty list, or an equivalent sequence for any other sequential though
15:04justin_smith,(seq ())
15:04clojurebotnil
15:04justin_smith,(seq '(1 2 3 4))
15:04clojurebot(1 2 3 4)
15:05justin_smithdino-: there is also the function not-empty, which unlike seq preserves the collection's type, but returns nil for empty input
15:05justin_smith,(not-empty {})
15:05clojurebotnil
15:05justin_smith,(not-empty {:a 0})
15:05clojurebot{:a 0}
15:05justin_smith,(seq {:a 0})
15:05clojurebot([:a 0])
15:05dino-huh, ok
15:06justin_smiththat should suffice for eg. translating common lisp code where they use empty as false in loops
15:07justin_smith(inc amalloy)
15:07lazybot⇒ 218
15:07justin_smithjust scrolled down to your answer on that keys-in thread
15:08amalloya lot simpler indeed, but slightly inconsistent
15:08dino-Ok, thanks again
15:12amalloyjustin_smith: i really love that pattern for exploring a decision tree
15:13amalloy(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:14justin_smithamalloy: maybe it should have a name?
15:15amalloyi'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:15justin_smithI bet it is the equivalent of some graph algo I don't know the name of
15:15amalloyjustin_smith: i mean it is literally just DFS
15:15justin_smithamalloy: right, but even if it is sufficiently abstracted, we can name it
15:15justin_smithOK
15:15justin_smithoh, right
15:15justin_smithd'oh
15:15clojurebotPardon?
15:15hellofunkamalloy: what is DFS mean?
15:15justin_smithclojurebot: d'oh
15:15clojurebotCool story bro.
15:16justin_smithdepth first search
15:16hellofunkoh, word
15:16amalloythe trick is figuring out how to think of your problem as a search tree so that Depth-First Search makes sense for it
15:16justin_smithright, that is often the issue with graph / tree stuff
15:16justin_smiththe hard part is seeing the graph / tree
15:16justin_smithafter that it's rote
15:16hellofunk"for" is pretty much a depth first logic with cut options, sorta
15:17justin_smithhellofunk: plus combinatoric expansion
15:17amalloyjustin_smith: i feel like this paths function is *almost* tree-seq
15:17justin_smithyeah, it's close, but it preserves some info tree-seq does not
15:17justin_smithit has more points of articulation
15:19SagiCZhaha.. i finally got rid of that pesky number one behind my nick. Behold!
15:19hellofunk,(source for)
15:19clojurebotSource not found\n
15:19justin_smithhellofunk: oh man, the source of that is insane
15:19justin_smithhave fun reading it!
15:19hellofunki thought there was a source finder on here
15:19amalloy$source for
15:19lazybotfor is http://is.gd/x33p56
15:19amalloy~def for
15:19benaiahanyone know of a good tutorial for writing command-line applications in clojurescript?
15:19justin_smithwoah, interesting use of notification
15:20amalloyyeah, i don't really understand why clojurebot sends that as a notice, compared to most of the stuff it says
15:20slipsetone could argue that the source for for looks quite like the source for doseq
15:21slipsetanyone in for a slight refactor to pull out the common stuff?
15:21justin_smithslipset: they have a lot in common
15:21slipsetjustin_smith: I would imagine
15:21amalloy"slight refactor". best joke of the day so far
15:21hellofunkamalloy: weird they link to different source files for for
15:21slipset~for
15:21justin_smithslipset: in clojure.core perf is more important than cleanliness in general
15:21clojurebotfor is like doseq, but for values instead of side effects
15:21amalloyhellofunk: they're running different versions of clojure
15:21slipset~doseq
15:21clojurebotdoseq is like for, but for side effects instead of values
15:21amalloy(inc clojurebot)
15:21lazybot⇒ 46
15:21amalloyand whoever taught him that
15:22slipsetgiven the docs I would imagine they have something in common
15:22hellofunk(inc whoever)
15:22lazybot⇒ 1
15:22hellofunkwell, just trying to help
15:23slipsetjustin_smith: I've come to understand that perf is quite important, but still.
15:25justin_smithslipset: 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:25tbaldridgepersonally I think doseq should move to something that uses reduce
15:25tbaldridgethat way doseq over a vector can use the vector's internal reduce logic
15:26slipsettbaldridge: 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:28gfredericks(defmacro doseq "shells out to DOS to determine the equality of x and y" ...)
15:28justin_smith{blake}: point is you compile once and run the js, so it *eliminates* the startup time hit
15:28benaiah{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:29justin_smithif you are repeatedly using the same utility, which is very common in the command line world
15:29justin_smithbenaiah: 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:30benaiahjustin_smith: perhaps I'll write one. The node CLI tooling is pretty well documented
15:30justin_smithbenaiah: that would be awesome
15:30justin_smithperhaps as a lein or boot task
15:32justin_smithbenaiah: 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{blake}That would be cool.
15:40zactshuh, see I'm thinking of using clojurescript for cli apps too
15:40zactsjvm clojure is just too slow for startup times
15:40justin_smithsomething in the wind, clearly
15:41justin_smithzacts: 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:41zactsyou know what would be cool would be the clojure equivalent to the scsh (scheme UNIX shell)
15:41zactsoh let me check that out
15:41justin_smithzacts: that actually would be an awesome thing to port to clojure, I would love that
15:41zactsyeah, perhaps I may look at it within the next few months for a fun side project
15:41justin_smithzacts: faster lein is documented here https://github.com/technomancy/leiningen/wiki/Faster
15:41slipsethttps://github.com/Raynes/conch
15:42zactsI already have too many projects at the moment, and I'm still a newbie
15:42justin_smithslipset: yeah, conch would actually be a decent starting point to doing something like scsh
15:43zactsnice
15:46justin_smithI like this trick: ##(update-in {:a 0} [:b] (fnil identity 42))
15:46lazybot⇒ {:b 42, :a 0}
15:46justin_smith(here I don't ever want nil as a value, so absence vs. nil value is a non-issue)
15:47zactsI wish I had some good books on design
15:47zactsdesigning abstractions
15:48amalloyso 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:48zactsbut perhaps that's something that can really only be learned from experience
15:48opqdonutjustin_smith: I usually just merge...
15:48amalloyneeds a million dang parameters
15:48zactsSICP I think approaches this though
15:48opqdonut,(merge {:b 42} {:a 0 :c 1})
15:48clojurebot{:a 0, :c 1, :b 42}
15:49justin_smithopqdonut: right, that is similar, but it does the wrong thing if the final map has {:b nil}
15:49justin_smithopqdonut: remember I said I didn't want nil values
15:49opqdonutoh right
15:49l1xif somebody is bored, what is the Clojuresq version of this https://gist.github.com/l1x/9f4c6d68e0a407185277?
15:49justin_smiththis way I can skip a winnowing step
15:51justin_smithl1x: I am 80% sure the answer involves using for
15:52amalloyhaha yes
15:52l1xjustin_smith: :)
15:52amalloyit is the same dfs, by the way
15:52amalloyto solve l1x's problem
15:52l1xjustin_smith: how can you recur with for?
15:52justin_smithamalloy: yeah, that is so parameterized that you may as well type the full thing out and just have the name for the pattern
15:52amalloyit's a tree search over a tree with branching factor 10 and depth number-digits
15:52justin_smith(regarding that refactor)
15:53l1xamalloy: hmm yeah
15:55amalloy&(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:55lazybot⇒ ("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:56amalloyor 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:56lazybot⇒ ("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:00amalloyl1x: does that make sense?
16:00l1xhuh
16:03l1xamalloy: thanks
16:06slipsetamalloy: same discussion, different place? http://stackoverflow.com/questions/18246549/cartesian-product-in-clojure
16:09amalloyslipset: yes
16:10benaiahcalling `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:13tcrayford____anybody ever got ring's wrap-reload middleware working with tools.namespace and component/etc?
16:18benaiahdoes this project.clj look correct for a clojurescript project? https://github.com/Benaiah/cljs-test/blob/master/project.clj
16:31notbrentbenaiah: https://github.com/swannodette/mies-node-template
16:31notbrentyou need to make some changes to your project.clj
16:31notbrent(sorry if that was answered already, my irc client timed out)
16:32dnolenbenaiah: looks ok though that build is missing an :id
16:32xyz_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:32benaiahnotbrent: no, yours was the first answer. thanks, that's quite helpful
16:33justin_smithxyz_: 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:34xyz_I can't use walk because I need to get a value from another map (a symetrical map if you will)
16:34clojurebotIt's greek to me.
16:35xyz_@justin_smith sorry, the paths and what ?
16:35justin_smithxyz_: 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:35justin_smithxyz_: 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:36xyz_justin_smith: yes the problem I had was with the path
16:36xyz_justin_smith: I'm not sure I get the reduce idea completely yet though
16:36justin_smithso 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:36justin_smithand for each path either update or not as needed with the help of the other map
16:37xyz_justin_smith: let me get back to digging ^^ I'll come back again
16:37amalloyxyz_: 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:38justin_smithxyz_ (reduce (fn [m path] (assoc-in m path update (get-in m2 path))) initial paths) ; something like this is what I meant
16:38justin_smithwhere 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:38xyz_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:39xyz_justin_smith: ok I'll try to digest that. Thank you
16:39amalloyso 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:40xyz_amalloy: exactly. like a schema or a merge
16:40hiredmanimagine the maps are flat instead of nested
16:41hiredman{:a {:b 1}} -> {[:a :b] 1}
16:41hiredmando the same thing you would do for the flat maps, but use assoc-in instead of assoc
16:41amalloyi 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:42xyz_amalloy: yes. This is an exercise for me, and I can't read cljx yet ^^
16:43xyz_hiredman: I think that this is what amalloy hinted at earlier ? with the keys-in function ?
16:43amalloywell. you don't need keys-in if your schema map is structured like {[:a :b] String} instead of {:a {:b String}}
16:44amalloybut of course you can use keys-in on the latter to produce the former
16:44xyz_amalloy: it's structured like a normal map (the latter)
16:44xyz_amalloy: yes I'll try that. That's a lot of info right now, let me get back to you guys Thanks again !
16:51gfredericksoh man core async depends on a sooper old analyzer
16:51adnauseaumclojure is gay and i hate it
16:51benaiahnotbrent: thanks a lot - that minimal project has made the cljs stuff much clearer than the documentation was able to alone
16:52notbrent:) no problem - dnolen did all of the work, i just linked to it ;P
16:59dbacarHi, anyone here with experience regarded to Jsoup?
16:59adnauseaumjsoup is gay and i hate it
17:00justin_smithamalloy: ping
17:00dbacarreally?, it seems nice , what would you recommend?
17:00adnauseaumjustin_smith: ping
17:00adnauseaumi'd recommend something that's less gay
17:00amalloyso 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:01justin_smithhehe
17:01justin_smithI think this guy wants to be restricted from using out channel
17:01adnauseaumnah bruh
17:01amalloyoh hey, i forgot i can do that
17:01adnauseaumwe gucci yo
17:01AeroNotixoh cool, someone to add to my ignore list
17:01adnauseaumwoah bruh u talkin shit? talk shit get hit
17:01AeroNotixyep. It's offical.
17:01amalloyi wonder if i can remember how
17:02AeroNotixadnauseaum: peace
17:02hiredmanI bet you just repsond with garbage to a syn too
17:02adnauseaumpzl8
17:02adnauseaumreecies peaceis
17:02adnauseaumFUCK YOU FAGGOT
17:02dbacarthere 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:03justin_smithdbacar: (:import whatever.Jsoup.Document.OutputSettings) I would think
17:04justin_smithof course make sure you have your project set up to pull in the dep too
17:05justin_smithoh, (: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:07dbacarjustin_smith: thank you, it worked, i tried the following and it throws an classnotfoundexc, do you know why?
17:07dbacar[org.jsoup.nodes Document Document.OutputSettings
17:07dbacar Attribute Attributes Comment DataNode
17:07dbacar Element TextNode]
17:07dbacarinside an :import
17:07travisrodmanamalloy: thanks for handling that.
17:07justin_smithdbacar: it's not Document.OutputSettings, it's Document$OutputSettings, that's the syntax for an inner class
17:08justin_smithand I don't think you can import the inner class (not 100% sure of that though)
17:08dbacari have a long way to go :(
17:08justin_smithamalloy: seconding that, thanks
17:09amalloyjustin_smith: you can import inner classes
17:09dbacarjustin_smith: it seems you can import inner classes the way you told
17:09amalloythey're just ordinary classes with funny names
17:11justin_smithoh, that's great
17:11justin_smithI just never had to do it yet
17:12tcrayford____get used to $ errywhere
17:19csd_`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:19justin_smithcsd_`: contains?
17:20csd_`hash-set would contain strings, hash-map would contain maps of user state
17:20csd_`keyed by username
17:20justin_smithwhy separate the keys into a hash-set?
17:21csd_`im just wondering whether that would be more efficient for purposes of checking if a name exists already
17:21justin_smithI am suggesting the function, called "contains?", which should be no slower than hash-set lookup
17:21csd_`i'm writing a toy irc server and am thinking about data structures
17:21justin_smithin case that wasn't clear and that just looked like a question
17:21justin_smithcool
17:22justin_smithanother options is find
17:22csd_`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:22justin_smith,(find {:a 0} :a)
17:22clojurebot[:a 0]
17:23dnolencsd_`: hash set is backed by a hash map, so no won't be faster
17:23justin_smithcsd_`: well, if you pass it to each function, it doesn't have to be global any more
17:23justin_smithyou can just call it "accumulated state"
17:23justin_smithand the fact that it never branches or backtracks is an implementation detail
17:24justin_smithand actually that is better than a global atom, if your design can pull it off
17:24csd_`i'm guessing it wouldn't work once i introduce concurrency
17:24justin_smithcsd_`: 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:24justin_smithcsd_`: yeah, once you have concurrency you probably want an atom or ref
17:25csd_`justin_smith: would you define either as a global?
17:25justin_smiththe atom, yeah
17:25justin_smithif you are just threading a value through, no, not as global
17:25csd_`ok
17:25justin_smithbut I would combine the atom with passing the value, if you do it that way
17:26justin_smithrather than doing lookup at each processing step in one request
17:26csd_`i havent worked with refs yet, haven't had any need
17:26justin_smithand then when done with it, put that back in the atom
17:26justin_smithyeah, 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{blake}I guess I could macro it up.
17:33justin_smith{blake}: there is a debug-middleware you can place between any two of the others
17:33justin_smithbecause hey, all the middleware are are wrappers, so throw it in the chain
17:34justin_smithor 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{blake}justin_smith: Ha! Yeah, I'm probably not that ambitious right now.
17:34justin_smith{blake}: for that, just throw the debug middleware in between each and every middleware
17:34justin_smithand have fun scrolling :)
17:35justin_smithin practice, it's usually a specific spot in the chain I am looking at, so I insert the debug middleware in that spot
17:35justin_smith{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:37justin_smith{blake}: woah, this one looks pretty cool https://github.com/magnars/prone
17:38{blake}justin_smith: Woah, indeed.
17:39justin_smithalso, .ninja domains are now available for $15
17:39justin_smithI hope clojure.ninja gets used for something awesome
17:42TimMcjustin_smith: It won't, it will be recruiters.
17:42justin_smith:(
17:42amalloyrockstar.clojure.ninja the secret subdomain for the best candidates
17:42justin_smithhaha
17:43justin_smithI hope that at least taco.cat ends up being something good
17:43amalloy_afk_ninjugh c'mon irc, gimme a break
17:43justin_smithoh, taco.cat is already up, and it's a silly python program
17:43tcrayford____justin_smith: taco.cat is a friend of mine's domain haha
17:44justin_smithoh, nice
17:44tcrayford____was *weird* as hell seeing it here
17:44{blake}Did they just abandon the TLD system or something?
17:44justin_smith{blake}: massive expansion I guess
17:44tcrayford____it's a money grab haha
17:45justin_smithof course it is
17:45{blake}justin_smith: Well, good. I hated to see ninjas left out.
17:45tcrayford____lots of folk trying to get new TLDs that are interesting
17:45TimMc.cat is Catalan though, not one of the new TLDs
17:45tcrayford____I uh, don't think google take TLD into account like they do the actual domain though, for exact matches
17:45tcrayford____yeah taco.cat is like 5 year sold
17:46justin_smithlooks like clojure.sucks is not taken
17:46justin_smithbut clojure.rocks is
17:46{blake}Ooh.
17:46tcrayford____another friend has "never.computer"
17:46justin_smiththat's a good one
17:46{blake}"Clojure.sucks but it.sucks less than everything else."
17:46tcrayford____(or at least, he used to)
17:47Ashclojure.pizza
17:47justin_smithsuch.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:56justin_smithdeps?
17:56justin_smiththat's a lot for one middleware
17:56AeroNotixsomething something transitives
17:57{blake}https://gist.github.com/anonymous/0862bc4fadb769c89f84
17:59justin_smithahh, of course, the logging libs
18:01{blake}It seems...excessive. That much code should fix your problem for you. =P
18:02{blake}Heh. I love lein under Windows. "Terminate batch job (y/n)"...then whatever you type, terminate.
18:02justin_smithprocess management under windows in general is "fun"
18:03{blake}For the "Dwarf Fortress" definition of "fun".
18:03justin_smithdoes 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:07justin_smiththat's cool
18:07justin_smithmy 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:10justin_smith(inc lein)
18:10lazybot⇒ 4
18:10tcrayford____(inc lein)
18:10lazybot⇒ 5
18:10tcrayford____you deserve more than that leinininininingen
18:11{blake}(inc lein)
18:11lazybot⇒ 6
18:11{blake}(inc ALL-THE-LEINS!)
18:11lazybot⇒ 1
18:11TimMcbanananananagen
18:12uptownwhat's the sanest way to mock environment variables as in (with-environment-variables {"foo" "bar"} (fact "foo should be bar" (env :foo) => "bar))
18:13uptown(assuming midje and environ)
18:13hiredmanthe sanest way to do anything starts with not using midje
18:13uptownoh um
18:13justin_smith(inc hiredman)
18:13lazybot⇒ 68
18:13{blake}uptown: Isn't the point of having environment variables not caring what's in them?
18:16AeroNotixenvironment variables do seem a weird thing to want to mock
18:21uptownwhat, then, should i
18:22TimMcAeroNotix: Uh, why?
18:22TimMcYou need to thread config into a program one way or another. Maybe I'm misunderstanding the midje question...
18:23AeroNotixTimMc: if your application's behaviour vastly changes with different environment variables, it's probably time to rethink.
18:23TimMcAeroNotix: I don't think that's a particularly unusual way to configure an app!
18:24uptownsorry, had a coffee accident here ha
18:24AeroNotixIt's not, I'm just saying that needing to test each individual setting in tests seems like the envvars control too much
18:24AeroNotixe.g.
18:24AeroNotixDB_HOST=foo
18:24AeroNotixis a good envvar
18:24AeroNotixSHOULD_USERS_HAVE_ACCESS_TO_FEATURE=true
18:24AeroNotixalso good
18:25AeroNotixWHEN_X_HAPPENS_DO_Y_AND_THEN_Z=true
18:25AeroNotixbad envvar
18:25AeroNotixnamsayin?
18:25uptownDB_HOST might want a different value for testing purposes
18:25uptownDB_HOST=foo_test
18:25AeroNotixsure, and you set that before running the test stuite
18:26AeroNotixDB_HOST=foo lein midje
18:26AeroNotixrun your test like that
18:26uptownin a repl, autotesting
18:26uptownif we agree that starting a repl is the way to go then okay
18:26AeroNotixI don't do that
18:26AeroNotixbut whatevs
18:28TimMcuptown: I don't think your tests should assume/test for any particular default for environment variables.
18:28justin_smithmy 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:28justin_smithand you just decide at startup which is the right config file to load
18:28justin_smithactually .edn is better than clj, but whatever
18:29justin_smithoh, and also resources/config/testing.clj too
18:30uptownTimMc: I'm not really testing the value itself, i just want to mock it for downstream purposes
18:33uptownjustin_smith: i'm trying to be 12factor compliant, which means trying to keep all the config in env
18:34uptownif env let me load a properties file programmatically just for test purposes i'd be happy that way
18:35TimMcuptown: 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:35justin_smithuptown: looking at 12factor's website, you can use resources/config/x.edn as long as they are not checked into version control
18:35AeroNotixugh, 12factor
18:35justin_smithuptown: and given that this is a security concern, you can also use an encrypted properties file
18:36justin_smith(with the key coming in from env of course)
18:39uptownTimMc: 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:39uptownthe failure is handled
18:41cbp#join #clojure-offtopic
18:41cbper
18:42uptownjustin_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:42justin_smithuptown: it wouldn't work to have a testing specific config?
18:43GlenjaminI normally put a thin layer between ENV vars and the app (eg. Config function/map)
18:43GlenjaminThen just use a different one for tests
18:43uptowni can certainly get it to but was hoping to keep the codepath and resource count at zero beyond the test module
18:44GlenjaminTurning env vars into config values is an app init concern
18:45GlenjaminOh, that's basically what Tim said
18:45mgaarecan 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:46uptownaha that works. thanks all
18:47uptownsay but if i can return to the previous topic: midje is evil?
18:47uptownwhat's the current flavor?
18:50justin_smithuptown: clojure.test, with the assistance of libs like expectations and test.check
18:51justin_smiththat'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{blake}There are probably people who are very strongly ambivalent about it, too.
18:53justin_smithuptown: 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:54TimMcuptown: I use midje. It is mostly nice, and when it isn't, I can fall back to building my own test utilities.
18:54justin_smitheg. 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:55uptowni inherited some code that uses midje and just kept using it.
18:55uptownhm i'll keep an eye on that
18:55uptownthanks
18:59TimMcMidje 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{blake}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{blake}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{blake}I'm not getting how that's handled.
19:05amalloyyour logging middleware must be applied inside of the wrap-resource handler insread of around it
19:06amalloychange 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{blake}I go to "/" and I see that request followed by the redirect to "/login"...
19:09{blake}Wait...app vs....I'm doing "handler/api app"...
19:15{blake}All my middleware: https://www.refheap.com/96607 and I still only see the main request, no resources, no AJAX.
19:36notbrentI 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:36notbrentI believe that would be easier to visually parse
19:37notbrentwhat do you folks think?
19:38notbrentfunctions 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:47xyz_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:49xyz_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{blake}Wouldn't "(case (desired-type)..." cause "desired-type" to be executed as function?
19:50xyz_blake: hopefully it's just something silly, I'm still learning Clojure syntax
19:50xyz_blake: oh maybe that's why. Let me try :)
19:51xyz_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:52xyz_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:53amalloyxyz_: you can't really use a 'case to match on Class literals
19:54amalloybecause Boolean is really a symbol, not a class, and 'case doesn't evaluate its test clauses
19:54xyz_amalloy: I just saw that now by googling for my error : http://stackoverflow.com/questions/12028944/clojure-case-statement-with-classes
19:54xyz_amalloy: does that seem correct to you ?
19:55amalloyyes
19:56xyz_amalloy: ok thanks. Time to learn about defmulti and defmethod then ^^
19:56amalloyi mean you can just replace (case x ...) with (condp = x ...) for a simple fix
19:57xyz_amalloy: oh intersting. I'll try that first then.
20:00bodie_notbrent, I think <! >! is clearer since the ! always comes after mutating functions, and the functions are < and >
20:00notbrentthat makes perfect sense
20:00notbrentthanks bodie_
20:00bodie_it is a little ugly though ;)
20:01notbrentindeed - I like with >! and !< how you can think of ! as a channel in the middle of two processes
20:01notbrentone on the left puts it on, one on the right takes it off
20:01notbrentbut the convention of ! after mutating functions should take precedence there for consistency
20:01notbrentunfortauntely
20:02notbrentunfortunately*
20:02bodie_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:03bodie_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:05notbrentalso curious about bodie_'s question
20:05amalloyyou can't run anything off of like "latest github commit"
20:05amalloyit needs to be a jar somewhere in the world
20:05amalloyyou can jar it up yourself and publish it, if you want a particular version to be available
20:06bodie_hmm, ok. then how would I go about including it as a dependency?
20:09notbrenthttps://github.com/ato/clojars-web/wiki/About#do-i-have-to-use-leiningen-with-clojars-and-clojars-with-leiningen
20:09notbrentin particular: https://github.com/technomancy/leiningen/blob/preview/doc/DEPLOY.md
20:09{blake}We use a local archiva server.
20:11bodie_notbrent, cool, thanks
20:12notbrentnp
20:15R0B_RODHello
20:15R0B_RODCurrently exploring the Clojure Koans
20:21n0n3suchmoan
20:22TEttingerloan
20:22n0n3suchloon
20:22TEttingergoon
20:22n0n3suchbufoon
20:22TEttingerheh
20:22n0n3suchlol
20:33notbrent(= ___ true)
20:42dangitI’m trying to use compojure with SS’s components. I can’t figure out how to get the component instance to the routes.
20:43dangitCan someone give me some guidance?
20:49nooniandangit: 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:49zactshuh, I think I may try the koans myself too
20:49zactswhat do they teach mainly?
20:49zactsor are they just like euler problems?
20:51nooniani 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:51dangitnoonian: thanks, that’s helpful
20:51zactsoh neat
20:51nooniandangit: np :)
20:52zacts"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:52zactsthat's cool, I'll do them then
20:53zactsthey are cooler than euler for what I want right now
21:06dokyhello 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:19justin_smithdoky: map is lazy
21:19justin_smithit won't do anything unless you consume the result
21:24TEttingerdoky: the more correct way is with doseq, but you can also force a lazy seq with doall after using map
21:25dokyjustin_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:25TEttingerlight table evaluates lazy sequences, just like the REPL will
21:25TEttingerbut a running program won't
21:25TEttinger(doc doall)
21:25clojurebot"([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:25TEttinger(doc dorun)
21:25clojurebot"([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:26justin_smithTEttinger: better yet, dorun
21:26justin_smithyeah
21:27dokyTEttinger: thanks doall works great :)
21:27dokyTEttinger++
21:28dokyjustin_smith++
21:28justin_smithdoky: 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:28justin_smith(inc TEttinger)
21:28lazybot⇒ 38
21:28doky(inc TEttinger)
21:28lazybot⇒ 39
21:28doky(inc justin_smith)
21:28lazybot⇒ 175
21:29dokyjustin_smith: i forgot
21:34zactshum.. I guess I'm stuck with JSON for now, as edn isn't really stable, and is subject to change
21:34zactsUnless you guys know of a better JSON alternative
21:36justin_smithzacts: I have had good luck with using cheshire for edn / json conversion
21:37justin_smithand also, edn hasn't really change much so far - though I guess there are no promises
21:38justin_smithbut for the subset of edn that converts directly to json, I wouldn't expect changes (strings, numbers, vectors, hash maps)
21:38TEttinger(inc justin_smith)
21:38lazybot⇒ 176
21:40TEttingerzacts: 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:40zactsjustin_smith: ah ok let me check out cheshire
21:40zactsjustin_smith: huh, perhaps I may consider a subset of edn yeah
21:41zactsTEttinger: well serializing clojure is just having literal clojure expressions in a text file.
21:41TEttingerhttps://github.com/sritchie/carbonite
21:41zactsI mean clojure is basically already an AST
21:41zactswhich is cool
21:41justin_smithzacts: also there is transit, if you want efficient transfer with json on the client end and clojure on the server end
21:41TEttingerright, but binary serialization is sometimes desirable (much smaller)
21:41zactsoh I didn't even consider that TEttinger
21:48zactshow about some good clojure general purpose parsing frameworks?
21:49zactskind of like ANTLR
21:49justin_smithinstaparse is popular
22:01zactscoolio
22:57R0B_RODSeeking some basic introductory instructions on programming using Clojure.
22:57R0B_ROD~book
22:57clojurebotbook is http://www.pragprog.com/titles/shcloj/programming-clojure
22:57R0B_RODThanks and good evening to all.
23:14AlwaysBCodingwhat 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:17fairuzAlwaysBCoding: how about core.cache?
23:20fairuzI 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:21AlwaysBCodingis there a good example anywhere of using core.cache with ring?