#clojure log - Dec 21 2012

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

0:00 amalloy: i don't know clojure's do-notation, but in haskell you can do it like: do {x <- return value; return (function x)}

0:01 sgeo_: In clojure.algo.monads at least, domonad puts an implied return around the last expression

0:01 So a bit like a list/monad comprehension

0:31 muhoo: frozenlock: is cljs-in-cljs a real thing?

0:31 ghadishayban: &(let [^{this should really throw an exception} foo 42] foo)

0:31 lazybot: ⇒ 42

0:31 ghadishayban: hilarious

0:32 muhoo: metadata on a vector?

0:32 ghadishayban: &(let [foo ^{this should really throw an exception as well} []] foo)

0:32 lazybot: ⇒ []

0:32 TimMc: That's... surprising.

0:32 bbloom: &(let [foo ^{this should really throw an exception as well} []] (meta foo))

0:32 lazybot: ⇒ nil

0:32 ghadishayban: see my comments on CLJ-1136

0:33 compiler bug

0:33 metadata in a let binding vec doesn't get evaled

0:33 amalloy: ,(let [foo ^{this should really throw an exception as well} []] (meta foo))

0:33 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: as in this context, compiling:(NO_SOURCE_PATH:0)>

0:34 bbloom: &(macroexpand '(let [foo ^{w t f ?} []] foo))

0:34 lazybot: ⇒ (let* [foo []] foo)

0:34 amalloy: i recommend using clojurebot for this, bbloom. lazybot probably messes up metadata

0:34 TimMc: Anything to do with lazybot's parser/expander?

0:34 mehwork: from a .clj file ran via lein run, how do you create an infinite stdin prompt that echo's back what you type each time you hit enter?

0:34 bbloom: ,(binding [*print-meta* true] (macroexpand '(let [foo ^{w t f ?} []] foo)))

0:34 clojurebot: (let* [foo []] foo)

0:35 bbloom: hm

0:35 mehwork: im trying everything i can google and nothing ever echo's back

0:35 bbloom: ,(binding [*print-meta* true] (macroexpand '(identity ^{w t f ?} []))

0:35 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading>

0:35 bbloom: ,(binding [*print-meta* true] (macroexpand '(identity ^{w t f ?} [])))

0:35 clojurebot: (identity [])

0:35 bbloom: *shrug* i've had bad luck with metadata

0:35 ghadishayban: print-meta won't affect that i believe

0:35 bbloom: (doc *print-meta*)

0:35 clojurebot: "; If set to logical true, when printing an object, its metadata will also be printed in a form that can be read back by the reader. Defaults to false."

0:36 ghadishayban: it's a bug in Compiler$LetExpr

0:36 TimMc: bbloom: You didn't print.

0:36 ghadishayban: TimMc: exactly

0:36 bbloom: TimMc: dur. yes, the repl is printing OUTSIDE heh

0:36 my bad

0:36 ,(binding [*print-meta* true] (prn (macroexpand '(identity ^{w t f ?} []))))

0:36 clojurebot: (identity ^{f ?, w t} [])

0:36 bbloom: ,(binding [*print-meta* true] (prn (macroexpand '(let [foo ^{w t f ?} []] foo))))

0:36 clojurebot: (let* [foo ^{f ?, w t} []] foo)

0:37 bbloom: hm yeah, gotta be a bug in LetExpr since it's not a bug in the let macro

0:38 anyway: what are people using metadata for outside of symbols and vars? i know that zip.clj uses them, but i feel like defrecord is almost always preferable. i'm curious if others ignore metadata as often as i do....

0:41 TimMc: Wait, so how is it that (let [foo ^{a b} []] foo) throws and (let [^{a b} foo []] foo) doesn't?

0:42 I would think that both would throw, actually.

0:42 Do metadata literals have an implicit quote?

0:43 amalloy: TimMc: [] gets eval'd, and foo doesn't, in that context. i imagine that's relevant

0:43 ghadishayban: good catch

0:44 it won't really affect type hints though:

0:45 amalloy: of course it does. (Class/forName "not real") isn't a meaningful type-hint if it doesn't get eval'd

0:46 TimMc: (prm `^{a (+ 1 2)}[]) ;;= "^{clj.core/a (clojure.core/+ 1 2)} []"

0:46 ^ (defn prm [s] (binding [*print-meta* true] (pr-str s)))

0:46 ghadishayban: but typically ^objects or ^floats

0:47 TimMc: ,(meta ^ints [])

0:47 clojurebot: {:tag #<core$ints clojure.core$ints@605af24c>}

0:47 TimMc: Hmm, some sort of special-casing there...

0:47 ghadishayban: do the bots support def?

0:47 TimMc: ghadishayban: Nope. Their sandboxes don't allow environment mutation.

0:48 amalloy: i believe the issue is that (let [^{:tag (Class/forName "x")} name val] ...) is equivalent to (let [name ^{:tag (list 'Class/forName "x")} val] ...)

0:48 TimMc: ghadishayban: By the way, you can /msg them to test stuff out.

1:00 pendlepants: would anyone recommend using an IDE for clojure development? noticed that intellij is $50 today, but am not sure how helpful it'd be.

1:01 technomancy: pendlepants: IIRC the clojure support for intellij works fine in the OSS version

1:01 pendlepants: oh, cool. thanks technomancy.

1:02 is the value in an IDE re: debugging and java interop, or are most people using emacs?

1:02 s/the/there/

1:03 Raynes: pendlepants: Most people are using Emacs, but plenty of people also use counterclockwise for Eclipse.

1:03 technomancy: most people use emacs. the value of an IDE depends on whether you end up working on large java codebases alongside your clojure.

1:03 Raynes: I don't think java interop is a factor, and there is some debugger stuff for Emacs too (ritz).

1:03 But if you're happy with something like Eclipse or Intellij, nobody will lynch you.

1:04 technomancy: I mean, that's where the distinctive strengths of IDEs stand out; it's impossible to navigate certain java codebases without a tool that's actually written in Java

1:04 but you can do a lot in clojure without ever having to do that; it depends on what you're writing

1:04 bbloom: it's impossible to navigate certain java codebases</message>

1:04 Raynes: I've yet to need an IDE.

1:04 But I've yet to work with a Java codebase.

1:04 Besides libraries, at least.

1:04 Nothing app-level.

1:05 pendlepants: that makes sense; I'm coming to clojure w/o a lot of java experience and was nervous that I may shoot myself in the foot without an IDE.

1:05 but that's heartening.

1:05 Raynes: I don't think an IDE will really help you with any foot shooting.

1:05 technomancy: pendlepants: for pure-clojure code you almost never need a stepping debugger

1:06 bbloom: (-> some (long sequence of code) with a random println (in the middle) tends to work out)

1:06 Raynes: Of course, if you're frustrated with Emacs it might turn you off of Clojure, so make sure that if you're not comfortable with it you use something you are comfortable with until you actually want to learn Emacs.

1:06 Chas Emerick, author of Clojure Programming, uses Eclipse for his Clojure development. No shame in it.

1:06 I mean, he has plenty of shame, but not because of that.

1:07 pendlepants: I'm used to vim and have been developing in that w/ some tmux stuff to get copy/paste into the repl.

1:07 Raynes: Vim works well for Clojure.

1:07 bbloom: pendlepants: time to upgrade to tpope's foreplay!

1:07 technomancy: don't switch from vim to emacs while trying to learn clojure at the same time

1:07 bbloom: pendlepants: https://github.com/tpope/vim-foreplay/

1:07 technomancy: your brain will explode

1:07 pendlepants: yeah, if vim's not a huge pain with clojure I'd just as soon keep using it.

1:07 Raynes: pendlepants: I actually switched from Emacs to Vim for a long time and was very happy. I only switched back to Emacs when I discovered evil-mode. If you're good with Vim, I recommend you just stay there.

1:08 technomancy: I really don't buy that as a general thing for everybody.

1:08 bbloom: Raynes: it's common enough to be ill advised

1:08 Raynes: Like, I learned Emacs and Clojure at the same time and I was like 13.

1:08 bbloom: Raynes: being 13 makes it far easier

1:08 technomancy: Raynes: yeah, but when you're older it's harder to learn new things

1:08 * Raynes rolls his eyes.

1:08 Raynes: Alright gramps.

1:09 I'll respect my elders and concede for now.

1:09 bbloom: Raynes: you didn't have to *unlearn* anything first :-P

1:09 technomancy: also when you have lots of free time =)

1:09 Raynes: I was really busy. Internet porn and what not.

1:09 bbloom: vim was hard for me after 5 years of visual studio

1:09 damn free copies for schools, that shit is like crack

1:10 just as bad for you.

1:10 technomancy: but unfortunately it's legal

1:10 bbloom: who do we sue?

1:11 Raynes: Sue Chris Granger for damages, bbloom.

1:11 He worked on VS.

1:11 :)

1:11 ibdknox: I had nothing to do with it

1:11 bbloom: .... so did i....


1:11 Raynes: technomancy: We have a traitor in our midst.

1:11 ibdknox: I wanted to create a sku for $50

1:11 not a free one ;)

1:12 technomancy: Raynes: you know what to do

1:12 ~guards

1:12 clojurebot: SEIZE HIM!

1:12 bbloom: i wrote a large portion of the XNA sample games... i'm like walter white over here...

1:12 Raynes: ibdknox: Were you just eavesdropping, or do you get highlighted on 'Chris' or 'Granger'?

1:13 technomancy: bbloom: if you're going to make this difficult...

1:13 ~gourds

1:13 clojurebot: SQUEEZE HIM!

1:13 amalloy: he gets highlighted on "Sue"

1:13 Raynes: Hahahaha

1:13 ibdknox: yep.

1:13 amalloy: years of microsoft paranoia

1:13 ibdknox: I actually happened to be looking

1:13 technomancy: amalloy: I was thinking along the lines of "A boy named..."

1:13 ibdknox: though I highlight my name to see all the bad things you guys say about me.

1:13 fuckers.

1:14 Raynes: ibdknox: Man, did you see all the people *thanking* us for deprecating noir?

1:14 It was spectacular.

1:14 ibdknox: It was the right thing to do :)

1:14 Raynes: A few people were sad and wanted me to be like "No, I was just kidding! Noir is back!"

1:14 But most of them were ecstatic.

1:14 bbloom: "how dare you build something for free and then get busy and change your preferences in design!"

1:15 Raynes: Well, he didn't go that far. :p

1:15 bbloom: notice: no question mark

1:15 technomancy: Raynes: that would have been great if April were closer

1:15 ibdknox: lol

1:15 Raynes: He said he had non-clojure developers writing Clojure at work and that they apparently incapable of putting two dependencies in project.clj instead of 1 and he needed Noir for them.

1:15 *shrug*

1:16 I tried my best to not sound snarky, but... that just smells bad.

1:16 amalloy: good thing you didn't hack into his computer and upgrade him, then

1:16 ibdknox: I understood what he was saying, but he's looking at the problem wrong

1:16 what he wants can easily be accomplished by simply creating a template for compojure/lib-noir

1:16 Raynes: ibdknox: Well, the problem is that he has developers who should probably not be writing Clojure in the first place if they aren't willing to actually learn and use it. I don't know what to say to that. We can't optimize for people who hate Clojure.

1:16 ibdknox: and then fixing up some docs

1:17 Raynes: ibdknox: I've got two things on my TODO re that goal.

1:17 augustl: pasting this here, in case it's a general JVM/leiningen solution for this problem, no idea if it's specific to datomic: https://groups.google.com/forum/?fromgroups=#!topic/datomic/iT6CVdagK5c

1:18 ibdknox: Raynes: oh?

1:18 Raynes: ibdknox: The first thing is getting a Noir to Compojure+lib-noir tutorial/migration guide thingy on compojure's wiki, and the second is somethin Andre Brehaut suggested which is possibly changing webnoir to be a tutorial for Compojure + lib-noir

1:18 ibdknox: also how did we get away from berating bbloom?

1:19 Raynes: Well, not necessarily a tutorial, but like a getting started sort of thing like is on the front page.

1:19 bbloom: i berate myself plenty

1:19 ibdknox: Raynes: sounds like the right thing to do :)

1:19 Raynes: Maybe port the tutorials and stuff.

1:19 ibdknox: Raynes: that also covers that guys points

1:19 pendlepants: bbloom: thanks for the link to vim-foreplay; this is great.

1:19 Raynes: What Compojure needs is a good documentation website.

1:19 ibdknox: yes

1:19 Raynes: And webnoir is a fine place to put it, as long as you don't mind getting rid of the old Noir tutorial stuff (or moving it to an 'old' link or something, which would be fine)

1:19 bbloom: pendlepants: don't take me, thank tpope

1:19 ibdknox: and I'm sure weavejester would love it if someone put one together :)

1:20 bbloom: thank*

1:21 Raynes: ibdknox: Anyways, if the world ends in a few hours, meet me half way through the country.

1:22 ibdknox: right at midnight the power went out here (I'm visiting NC)

1:22 it has since unfucked itself

1:22 bbloom: power company have a sense of humor?

1:22 Raynes: You and amalloy and I could survive an apocalypse

1:23 ibdknox: Raynes: I have a fair number of unusual skills that would be very useful in such a situation

1:23 technomancy: I wonder if I'll ever get tired of ~guards

1:23 ibdknox: technomancy: I never do

1:23 technomancy: ibdknox: good to know it's not just me

1:23 ibdknox: bbloom: I'm fairly convinced it was someone being funny

1:23 Raynes: technomancy: I always cut up when you do ~gourds afterwards.

1:23 amalloy: $eball

1:24 damn. Raynes, how do i ask him if technomancy will get tired of ~guards?

1:24 Raynes: amalloy: Long since removed.

1:24 IIRc

1:24 technomancy: will I ever tire of ~guards??

1:24 lazybot: technomancy: Definitely not.

1:24 amalloy: i guess i could cheat: o great lazybot, will technomancy ever grow tired of ~guards??

1:24 lazybot: amalloy: Uh, no. Why would you even ask?

1:24 technomancy: sweet

1:24 Raynes: I deleted a lot of the old fun plugins because nobody cared about them and I got tired of rewriting lazybot's core and having a million pointless plugins to update.

1:24 But that's probably because I did too much core rewriting.

1:25 technomancy: clojurebot: botstack is <reply>/me puts lazybot on his head and gropes blindly for a third bot to complete the stack.

1:25 clojurebot: Alles klar

1:26 ibdknox: lol

1:26 technomancy: another classic from the Emacs channel

1:26 but they actually have three bots in there, so it's a bit less awkward

1:27 bbloom: clearly somebody just needs to write a 3rd bot

1:28 technomancy: did we have a haskell bot at one point?

1:28 or no, lazybot speaks haskell

1:28 ibdknox: correct

1:28 amalloy: $heval [1,2..10]

1:28 technomancy: chouser_log is a bot

1:28 amalloy: damn it. i can't do anything right

1:51 witt3rd: hello. may i ask a lighttable question (quick)

1:52 bbloom: ibdknox ^^

1:53 just ask

1:54 witt3rd: is there a known issue in the latest build (OSX) with the instarepl eval munging the fn names with od chars

1:54 (def ï·‘'fn (fn [n] (+ n n)))

1:54 (ï·‘'fn 4) => 8

2:14 ibdknox: witt3rd: it is now: https://github.com/Kodowa/Light-Table-Playground/issues/237

2:14 witt3rd: :-)

2:15 ibdknox: thanks :)

2:15 ro_st: ibdknox - just curious, have you done anything with websockets and cljs?

2:16 ibdknox: yeah

2:16 ro_st: what did you use on the backend? aleph?

2:16 ibdknox: though in every case I cheated

2:16 ro_st: oh, how so?

2:16 ibdknox: aleph originally

2:16 now socket.io

2:16 ro_st: so node.js on the back

2:16 ibdknox: I didn't need to support anything other than hcrome

2:16 chrome*

2:17 Yeah, now it's node

2:17 aleph worked fine though

2:17 didn't try any scaling with it

2:17 Ember-: ibdknox: hmm, have I missed something or does the Light Table support function navigation, meaning that I can "dive" into the definition of a function from a call

2:17 similar to ctrl+lmb in eclipse+java or f3 in counterclockwise?

2:17 ibdknox: Ember-: not in the current version

2:17 Ember-: ok

2:17 so I'm not dumb :)

2:18 ro_st: ok, thanks. we plan to go pretty large with websockets and i've seen a fair number of complaints about aleph's overall speed

2:18 ibdknox: though some changes I needed on the CodeMirror side came in that will let me do the function "bubbles" correctly this time

2:18 Ember-: that's one of the last things preventing me from using it for real

2:18 ibdknox: ro_st: I wrote a netty-based websocket server previously

2:18 that was blazingly fast

2:18 orders of magnitude faster than node at the time

2:19 Ember-: just to confirm I understand, you're talking about go-to-definition right?

2:19 Ember-: yes

2:19 loving light table so far btw, happy I contributed in the kickstarter

2:19 make it shine ;)

2:20 ro_st: it's going to be so cool once we have websockets and storm drpc set up

2:20 ibdknox: Ember-: I'm hoping I'll get to announce a hire or two soon, which will mean that will come even faster :)

2:20 ro_st: real-time all the things

2:20 Ember-: I'm pretty sure that six months from here it's light table all the way for me with clojure

2:20 oh really cool

2:21 ro_st: ibdknox: did you ever look at atmosphere? https://github.com/Atmosphere/atmosphere

2:22 looks like it suports socket.io's protocol

2:22 we need a jvm solution so that we can leverage datomic's peer caching

2:23 brainproxy: need to take a break and play w/ something .. different .. tcl or rebol/red?

2:23 ibdknox: ro_st: I did not

2:23 ro_st: when I looked into that stuff (where I actually needed to scale) I'm fairly certain that wasn't well known :)

2:23 augustl: I prefer (with-thing (fn [thing] .. do stuff .. )) over a macro style (with-thing [thing] .. do stuff ..), am I crazy? :)

2:24 ro_st: no. functions always compose better than macros!

2:25 ibdknox: ro_st: this has been gaining some steam lately https://github.com/sockjs/sockjs-client

2:25 ro_st: and it's got a vert.x impl (JVM)

2:25 augustl: ro_st: that's what I'm thinking too

2:25 brainproxy: the aleph/lamina guy said he was looking into sockjs

2:26 augustl: I suppose if it's called a couple of thousand times per second a macro will be faster since you avoid the function call? :S

2:26 brainproxy: but I haven't seen any movement in that regard, i.e. on his github account

2:27 ro_st: sockjs looks great

2:27 brainproxy: "looking into" meaning considering a aleph/lamina based clojure server that would implement sockjs "spec"

2:28 ro_st: atmosphere looks like it's pretty thoroughly battle tested

2:29 brainproxy: yeah, but i was hunting for a clojure wrapper/bridge to it, didn't see anything

2:29 augustl: ro_st: I prefer to use something like faye instead of socket.io or sockjs, faye uses fewer hacks

2:29 brainproxy: not that clj java interop is bad, but it's just nice to have idiomatic functional api

2:29 augustl: sock.io has a lot of pretty nasty hacks in order to get cross origin messaging

2:29 ro_st: got a link, augustl?

2:29 brainproxy: augustl: faye is cool

2:29 augustl: ro_st: http://faye.jcoglan.com/

2:29 brainproxy: but ... you're buying into the whole bayeux thing

2:29 augustl: brainproxy: yeah I'm using it a lot

2:30 true, but the java comet something project supports it

2:30 ivan: most things, including sockjs, think it's okay to reorder or lose data

2:30 you have to think about HTTP for over 10 minutes to see the problem

2:30 brainproxy: augustl: right because faye is an impl of bayeux, which is the basis of cometd

2:30 augustl: ro_st: example, if you try to use sock.js in a HTML4.1 frameset document in IE7 or lower, a popup is opened for each request :)

2:30 and for a project I needed to use a html4.1 frameset doc

2:31 ro_st: yikes

2:31 we only support modern-ish browsers anyway. ie9+.

2:31 augustl: this is mostly because it does really funky stuff to achieve cross origin comapt, I think it submits forms in an iframe or smt

2:31 brainproxy: ivan: socket.io, i think, has an optional ack api that will allow you to implement logic which could avoid reordering and msg loss

2:32 ivan: brainproxy: if you take a look at the ack implementation, you find that it's used for some nonsense application-level confirmation, and not used to implement a reliable stream

2:32 brainproxy: ivan: that's what I was going to say next

2:32 :)

2:32 the long and short being that it's best to use it in scenrios where lossy notification stream isn't a big deal

2:32 ivan: someone wrote a BrowserChannel server for Clojure

2:33 ro_st: looks like i have my homework cut out for me. thanks for the options, all

2:33 browserchannel - that's in google closure js, isn't it?

2:33 this, ivan? https://github.com/thegeez/clj-browserchannel-demo

2:33 ivan: yes. and it is reliable and used by gmail.

2:33 ro_st: https://github.com/thegeez/clj-browserchannel too

2:33 ivan: not sure if the server is any good though

2:33 yes, that's the one

2:34 if I had infinite time I would port my Minerva server from Twisted to some Clojure thing

2:34 ro_st: interesting. this looks pretty compelling

2:34 what we'd be using it for is pretty well defined

2:34 brainproxy: yeah, but browserchannel is not websocket, right?

2:35 ro_st: correct

2:35 http://thegeez.net/2012/04/03/why_browserchannel.html

2:36 ivan: if you think about the problem for even longer you discover that connection-oriented semantics are pretty crap

2:36 brainproxy: can't remember if faye websocket guarantees message order

2:36 ivan: CCNx probably has good ideas

2:36 websocket does

2:36 is faye websocket not websocket?

2:36 ro_st: i'm open to any solution that allows bi-di browser/server comms on the jvm

2:37 brainproxy: ivan: sorry for confusion

2:37 faye is an implementation of bayeux protocol

2:37 http://svn.cometd.com/trunk/bayeux/bayeux.html

2:37 but bayeux specs http, nothing about websocket

2:37 ivan: I can't remember what exactly was wrong with bayeux but I think it was in my not-even-wrong category

2:37 brainproxy: so faye's maintainer implemented his own idea for realizing bayeux over websocket transport

2:38 that's what i meant by faye websocket

2:38 but there is a library called faye-websocket which happens to a be just a websocket impl for node.js, nothing to do w/ bayeux

2:39 ivan: cometd is an implementation of bayeux .. i think

2:40 ivan: last I checked, yeah

2:40 brainproxy: imo, the real problem w/ sock, etc. is that devs start to drift into rpc/rmi mindset

2:42 and so create opaque "pipes" for data transport, when they would be better off using rest/hypermedia principles for their web apps/apis

2:42 ivan: the content-centric networking talk is a must-watch

2:43 the only problem is that it's much harder to design such a thing than dumb pipes

2:43 ro_st: we're using event sourcing for our client side data and persistence models

2:43 ivan: http://www.youtube.com/watch?v=oCZMoY3q2uM

2:43 brainproxy: have your read amunsen't "hypermedia oriented design"?

2:43 ivan: don't think so, I'll check it out

2:43 brainproxy: *amundsen

2:43 * ivan wonders when Datomic clients will run in a browser

2:44 ro_st: right now it's one way over ajax. we want to use bi-di to allow events to come back into the browser from the server, so that, eg, users can collaborate in a workspace

2:44 same events as normal, just coming from a different place

2:44 brainproxy: ivan: http://amundsen.com/articles/hypermedia-oriented-design/

2:44 ro_st: ivan: Datomic has rest api, so right now :-)

2:45 brainproxy: ivan: also see http://amundsen.com/hypermedia/profiles/

2:54 augustl: so.. I have a bunch of IO objects, separate ones for writing and reading. As soon as someone writes to the writing one, the associated reading one should die, but not until existing users of the reading one are finished. Suggestions? :)

2:54 I'm thinking plain old reference counting, but perhaps there's something more clever I can do

2:55 also, if someone writes, and two readers are still alive, and a new read request comes along, that request should get a new reader, not the old one

2:59 amalloy: so like...(let [io-objects (ref (repeatedly make-new-io-object))] (defn reader [] (first @io-objects)) (defn writer [] (dosync (let [ret (reader)] (alter io-objects rest) ret)))), augustl?

3:01 augustl: amalloy: sec, interpreting :)

3:01 amalloy: hmm, don't think so. I should probably have explained it better..

3:02 each read happens via http requests so they are completely stand-alone. So I'm thinking a (with-reader ...) type macro that does reference counting

3:05 callen: I feel like this is going to be really dumb, but I'm going to ask anyway

3:05 if I have a function returning [ [] [] [] ]

3:05 and its result is going inside of another vector, how do I splice the sub-vectors into the enclosing vector?

3:06 augustl: callen: mapcat does this

3:07 mapcat is for mapping _and_ concatenating in one go though

3:07 callen: I don't need to map.

3:07 I think the answer to my question was concat.

3:08 augustl: ,(reduce concat [[1] [2] [3]])

3:08 clojurebot: (1 2 3)

3:09 mthvedt: ,(apply concat [[1] [2] [3]])

3:09 clojurebot: (1 2 3)

3:09 augustl: ah

3:10 mehwork: what's the proper way to return true from a defn?

3:10 amalloy: true

3:10 mehwork: ah no parens

3:11 amalloy: parens are always for calling functions

3:29 ro_st: and for list literals, when quoted

3:29 '(:a :b :c)

3:32 borkdude: or inside macro's, like ns

3:32 ro_st: yes

3:33 borkdude: usually return true or false from a function involves a decision which has already the value true or false, so that can be returned

3:36 bbloom: or (boolean that)

3:36 which i'll sometimes do to prevent callers from taking a dependency on the fact that i just happened to use 'or or 'some to implement my function

3:38 mehwork: in a cond check how do you use a function that returns boolean as a test? cond (is-whatever "arg1") (println "yep") gives an error

3:38 callen: is there a good/established way to manage application configs in Clojure? particularly when handling prod vs. local/testing

3:39 ro_st: callen: we use env vars

3:39 only sane way. config in the git repo is a bloody pane

3:39 s/pane/pain

3:39 http://www.12factor.net/config

3:39 bbloom: i always prefer env vars plus a separate config repo

3:39 the config repo contains config for all deployed software

3:40 ro_st: we have a pallet repo which has everything

3:40 so i guess i concur :-)

3:40 bbloom: mehwork: what error do you get?

3:40 callen: oh I see, this is for people terrified about configs getting into source control

3:40 bbloom: callen: no, i want my configs in source control

3:41 but configs are a separate concern since they span multiple versioning boundaries

3:41 ro_st: yes. because it's a pain with multiple servers (prod/test/dev/dev/dev)

3:41 callen: I never really had that much of a problem with it.

3:41 bbloom: it wasn't an issue for us until we had 5+ smaller programs, each in it's own language

3:41 then env vars became the only sane approach

3:41 callen: in Python/Flask we used settings.cfg for prod, test_settings.cfg for local dev, staging_settings.cfg, experimental_settings.cfg, etc

3:42 bbloom: and we were duplicating config per project

3:42 callen: and pointed at each file based on ENV var.

3:42 bbloom: yeah, only need a small handful of env vars

3:42 callen: just the one, for us.

3:42 bbloom: often YOURCO_ENV is enough

3:42 ro_st: the solution we have is one that we no longer need to think about

3:42 callen: it didn't require any thought on our part either.

3:42 bbloom: but sometimes YOURCO_HOST and a few others are nice to have

3:43 for app-specific, deployment-independent config: by all means, put that in your repo and check it in :-P

3:44 ro_st: https://www.refheap.com/paste/7773

3:45 works nicely for us

3:47 mehwork: bbloom: unable to resolve symbol "arg1" in this context

3:47 bbloom: mehwork: refheap your code

3:48 mehwork: fixed now, it was a typo

3:48 bbloom: heh

3:48 mehwork: refheap?

3:48 clojurebot: refheap is gist

3:48 tomoj: lol

3:48 bbloom: ~pastebin

3:48 ro_st: refheap.com

3:49 bbloom: ~paste

3:49 clojurebot seems lazy

3:50 tomoj: grr.. I want to make my cljs port of clojure.test support asynchronous tests, but it uses a bunch of dynamic variables

3:51 bbloom: :-/

3:51 tomoj: so i think most async test frameworks out there are pretty terrible

3:52 tomoj: specifically in the way they handle async?

3:52 bbloom: 90% of the time, tests don't need any branching or looping, so you can write asynchronous tests synchronously by queuing every side effect and assertion, then having a test timeout

3:52 much more pleasant than (expect n-asserts) etc

3:53 tomoj: etc includes calling a callback to indicate that you're done?

3:54 wouldn't that mean you have to wait for the timeout on every test? if the timeout is pretty short, maybe not so bad

3:54 bbloom: it's a little harder in a more general context, but skrenzel has an awesome coffeescript browser integration test library that he refuses to find the time to open source.... i'll convince him to do that eventually

3:55 tomoj: you can run async tests in parallel, so timeouts are overlapping

3:57 tomoj: and then you need some way to say "this test isn't safe, don't run it in parallel"?

3:58 well I'm thinking of browser integration tests there, but you can't really do that with cljs.test anyway

3:58 bbloom: i haven't thought about the general case of unit tests deeply enough. with browser integration tests, you have a limited set of operators like click, fill, navigate, send_keys, etc

3:59 and all those operators do is queue.append

3:59 and you also have operators like assert_location, has_text, etc

3:59 none of those operators take callbacks

4:00 tomoj: better not have those running in parallel, though, right? unless you have multiple browser windows, one running each test?

4:00 bbloom: right

4:00 tomoj: example asynchronous integration test https://gist.github.com/4351531

4:01 works super smoothly & is blazing fast

4:01 using the queue strategy

4:02 we had 100+ of those tests & our non-programmer CEO wrote most of them via copy paste :-)

4:04 other than things that were integration testable, we had very little async javascript

4:05 tomoj: nice, even cucumber doesn't claim to be ceo-writable :)

4:06 bbloom: english is a terrible programming language :-P

4:06 to be fair, our CEO was smart enough to learn and ultimately prefer both HAML and SASS

4:07 anyway, if you're doing an async testing framework in cljs, consider the queue approach! would love to see what you come up with :-)

4:07 augustl: hmm, I need to create I/O objects inside dosync, does that make any sense at all? If the transaction runs multiple times I'm in trouble since I'll end up with unclosed IO objects

4:08 tomoj: my first tendency is to just write tests that return promises

4:08 bbloom: augustl: describe your use case and why/how you elected to use refs

4:09 augustl: it's probably easier if I describe my overall goal, paste coming up

4:09 bbloom: tomoj: as useful as promises are, i think this idea of "let's use promises all the time every time!" is flawed

4:09 i'd prefer a very limited async api surface

4:09 which is difficult if you have a REST api or similar

4:10 but even if you have a single api-call central point, you can use it in lots of places, and so have lots of promises

4:10 tomoj: in cljs.test I just imagine being able to do (deftest foo [done] (js/setTimeout #(do (is (= 42 42)) (done))))

4:11 then a promise library (which is what I'm testing) can I guess provide its own deftest that expects the test to return a promise

4:11 bbloom: sounds reasonable

4:11 tomoj: in the queue approach, I guess if a test times out with no assertions, that's a failure?

4:12 callen: bbloom: re: HAML/SASS -> fairly analogous to hiccup/clj-style.

4:12 bbloom: tomoj: yes

4:12 tomoj: but you also need to handle assertions coming after the timeout has already expired: also a failure... a *perf* failure :-)

4:13 callen: i'm aware

4:13 callen: bbloom: just humming. Hacking on a ring app right now.

4:14 bbloom: using hiccup, contemplating the merits of clj-style.

4:14 bbloom: callen: did you also evaluate https://github.com/paraseba/cssgen ?

4:16 tomoj: I wonder if it acceptable for a cljs bound-fn stopgap to ignore set!

4:17 augustl: bbloom: https://www.refheap.com/paste/7775 - or anyone, not just bbloom :)

4:17 bbloom: tomoj: you mean with respect to root bindings vs dynamic bindings?

4:17 tomoj: yeah

4:18 augustl: my problem is the "TODO" part. As soon as someone writes to the index, I want to expire the index reader so new calls to with-index-reader creates a new one. But when all existing parallel users of with-index-reader ends, I need to close it

4:18 since it's an I/O object

4:18 bbloom: augustl: you're only altering a single ref in each transaction. why not use atoms?

4:18 tomoj: since cljs will allow you (?) to do (binding [*foo* 42] (set! *foo* 43) ((bound-fn *foo*)))

4:18 for which a stopgap will return 42

4:18 augustl: bbloom: can I use atoms for atomic "get or set"?

4:18 bbloom: (doc atom)

4:18 tomoj: but people shouldn't be doing that anyway :/

4:18 clojurebot: "([x] [x & options]); Creates and returns an Atom with an initial value of x and zero or more options (in any order): :meta metadata-map :validator validate-fn If metadata-map is supplied, it will be come the metadata on the atom. validate-fn must be nil or a side-effect-free fn of one argument, which will be passed the intended new state on any state change. If the new state is unacceptable, the validate-fn should return fa

4:19 bbloom: that's not a super helpful doc string if you don't knwo what an Atom is :-P

4:19 augustl: :)

4:19 I thought all operations on atoms were outside a transaction

4:19 bbloom: augustl: http://clojure.org/atoms

4:19 augustl: since you call "swap" without dosync

4:19 that is, you don't need to put it in a transaction

4:19 bbloom: so 90% of the time, you want an atom

4:19 augustl: so atoms can do atomic "get or set"?

4:20 bbloom: the purpose of an atom is to do atomic compare-and-swap

4:20 via ##(doc swap!)

4:20 lazybot: ⇒ ------------------------- clojure.core/swap! ([atom f] [atom f x] [atom f x y] [atom f x y & args]) Atomically swaps the value of atom to be: (apply f current-value-of-atom args). Note that f may be called multiple times, and thus should be free of side ef... https://www.refheap.com/paste/7776

4:20 bbloom: there's a sort of implicit "transaction" around f

4:20 augustl: I see, so I could pass my own function that gets or sets?

4:20 bbloom: ,(let [x (atom 10)] (swap! x + 5) x)

4:20 clojurebot: #<Atom@4a1bb681: 15>

4:21 bbloom: augustl: right

4:21 also available ##(doc reset!)

4:21 lazybot: ⇒ ------------------------- clojure.core/reset! ([atom newval]) Sets the value of atom to newval without regard for the current value. Returns newval. nil

4:21 augustl: makes sense, the values inside the function you pass to swap doesn't need to be derefed so they're in a transaction

4:21 bbloom: yeah

4:22 augustl: still not quite sure how to handle all my side effect-y IO objects, and I now see that my paste is kind of messy and doesn't really showcase my problem, so I need to think about this some more ;)

4:22 bbloom: refs are for when you have to coordinate writes between multiple mutable places

4:22 and even then atoms are often better if you can get away with a map inside an atom

4:22 augustl: bbloom: I think I might need to coordinate multiple state changes though

4:23 as soon as someone gets an index writer, it's associated index reader should be tagged as "please die"

4:23 then as soon as all current users of the index reader (via with-index-reader) finishes, it should be closed

4:23 hmm, that's just one state change :)

4:23 bbloom: hmm what are the ownership semantics of a writer?

4:24 how many/which threads are responsible for IO?

4:24 augustl: bbloom: index writers stay alive forever. Then HTTP requests comes in and reads and writes.

4:25 so it's very side effecty indeed, since individual threads/http requests will read and write in any order at any time

4:25 bbloom: there can be multiple simultaneous writers per index ?

4:25 augustl: no, just one writer per index

4:25 but multiple calls to the same writer. That is handled by the writer code though, it's thread safe

4:26 bbloom: hm, generally, i try to isolate IO to a small number of workers and communicate with them

4:26 particularly for network, one IO thread is often enough for a gigabit

4:26 but disk IO is different....

4:27 how many indexes do you expect to have?

4:28 augustl: bbloom: a bunch, there's one index per main domain object in my system

4:28 bbloom: augustl: so on the order of a dozen?

4:28 augustl: probably not more than hundreds or so per server though

4:28 bbloom: hm

4:28 augustl: s/server/process

4:28 bbloom: have you considered an agent per index with async writes?

4:28 augustl: go on :)

4:29 ah, I think I see what you mean

4:29 bbloom: you basically have one atom which is a map of domain object -> table manager

4:29 the table manager is an agent which is basically the current state, read/write/etc

4:29 and you send messages to the appropriate agent to perform IO

4:30 this way you use a swap! on the db atom to load a table

4:31 (send (@db :foo) some-write-operation bar) ; might be send-off, i can never remember which is which

4:31 augustl: hmm

4:32 bbloom: for reads, you can pass the agent a promise and then block on that

4:32 augustl: might as well make my lucene indexing eventually consistent :)

4:32 bbloom: queues and messages: damn good ideas that more people need to employ more often :-)

4:34 augustl: considering using elastisearch instead.. Spending time on lucene details is not important for my business :P

4:35 bbloom: also valid :-)

4:35 augustl: and it makes my system composed of simple services, yay

4:37 bbloom: i'm not sure i like the name "simple service"

4:37 i'd call them "utility services" in the same vein as utility functions and utility programs

4:37 :-)

4:38 augustl: hmm, I don't think of queues and full text search systems and databases as utilities

4:40 bbloom: well they certainly aren't simple! :-)

4:44 ro_st: complections? :-)

4:45 augustl: datomic comes close, but I actually couldn't use it in my project since the datomic-free peer library fails to load since I depend on lucene 4 :)

4:45 so I suppose that means datomic complects my app with the datomic peer or something like that? :P

4:47 not sure what the actual problem was though.. When I removed my lucene 4 dependency, leiningen downloaded lucene 3.6. So I guess datomic just needs an explicit dependency on 3.6 since it seems to just use lucene 4 when it's available.

4:48 tomoj: that sucks

4:49 augustl: I posted on the mailing list, hopefully it will turn out to be my problem. It probably is, since I'm new to all things JVM!

4:49 tomoj: seems like there should be a way to deal with that, which doesn't involve OSGI cus wtf is that

4:50 augustl: speaking of elastisearch. Are there any libraries I can use that manages the http details for me? Retries, keep-alive connection pooling, etc

4:52 tomoj: clj-http has both of those features

4:53 augustl: ah

4:54 hmm, I'll be doing my http calls inside ring request handlers. Should I just wrap my entire handler in a middleware that does with-connection-pool?

4:55 sounds dangerous though, since then it probably applies to all calls to clj-http that might happen in libraries etc

4:55 tomoj: oi

4:55 augustl: so some out of sight pool would be nice

4:56 tomoj: and of course the only way to pass it in is with the dynamic var

4:56 oi

4:56 augustl: :(

4:56 I hate it when libraries does that!

4:57 tomoj: fairly easy patch it seems though

4:57 augustl: I could just bind it on every call I do, since I have one thread per request anyway

4:57 like, (with-connection-pool my-global-pool do-stuff)

4:57 tomoj: except with-connection-pool is even less usable than that

4:58 augustl: I meant my own with-connection-pool, sorry

4:58 where I manually set the binding

4:58 tomoj: ah, I see, yeah

5:00 augustl: complects my system with ring handlers though.. I might not always have one thread per business logic operation, meh.

5:01 suppose I could just use the Java lib from apache directly

5:03 seems that irccloud.com is down :)

5:03 tomoj: I don't think it should be hard to patch clj-http to just accept a conn manager in the request

5:03 augustl: only problem would be if it already makes use of arity dispatch

5:06 tomoj: nah it's a big map https://github.com/dakrone/clj-http/blob/master/src/clj_http/core.clj#L179

5:06 augustl: ah, nice

5:06 I'll put it on my TODO list for the evening :)

5:08 tomoj: would be nice to also split with-connection-pool up to make it easier to get ahold of a conn manager

5:08 hmm

5:08 https://github.com/dakrone/clj-http/blob/master/src/clj_http/client.clj#L726

5:09 wat?

5:09 clojurebot: For Jswat: start clojure with -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888

5:12 augustl: tomoj: :D

5:12 hmm, just passing the connection manager in with the map makes sense, in order to not mess with arity

5:13 (http/post "http://foo.com" {:connection-manager my-manager})

5:14 one of the lessions I've learned in my 4-5 months as a Clojure programmer, is that complex encapsulation really sucks.

5:21 ro_st: would you go back to your previous language(s)?

5:25 clgv: how do I "freeze a snapshot to [a] dated version" in leiningen?

5:25 augustl: ro_st: I still program a lot of user interfaces, mutable single threaded environments are still status-quo there..

5:25 ro_st: building systems with OO would be extremely painful now though

5:27 ro_st: +1.

5:27 to think i was going to use Rails for the backend -shudder-

5:29 augustl: I'm writing a rails app nowadays too actually, but I think of it as a front-end only. Most of the core business stuff is on the JVM (integration with 3rd party invoicing system, etc)

5:33 ro_st: condolences

5:34 fredyr: how are you integrating your rails app with the jvm?

5:35 running a queue inbetween?

5:36 augustl: fredyr: yup

5:36 and the JVM stuff writes directly to the same postgres db

5:36 fredyr: nice

5:36 which queue?

5:36 augustl: haven't decided yet :)

5:36 fredyr: i've been working with rabbit lately

5:37 ro_st: rabbit is nice

5:37 fredyr: i can recommend that one

5:37 yeah definitely

5:37 and the bindings for JVM and ruby are good

5:37 augustl: as long as it talks something like stomp, it's pretty portable anyway

5:48 fredyr: ok haven't looked at stomp

6:12 silasdavis: Could someone tell me why (map pretty-message (message/all)) works, (-> (message/all) (map pretty-message)) doesn't?

6:13 Don't know how to create ISeq from: pretty_message

6:13 ah I thought -> inserts as second argument

6:14 cemerick: no, -> is thread-first

6:14 ->> is thread-last

6:14 silasdavis: ah it is the second element in the list which is hte first argument

6:14 thank you

6:14 cemerick: yup

6:14 np

6:14 clgv: how do I "freeze a snapshot to [a] dated version" in leiningen?

6:15 silasdavis: is (->> seq (map f) (map g) (map h)) an idiomatic way of chaining maps?

6:15 is there a better way?

6:16 bpr: silasdavis: you could do (map (comp h g f) seq)

6:17 silasdavis: oh of course

6:17 thanks

6:17 bpr: sure thing

6:18 but on the other hand if there are reduces and filters, etc. the threading macro can be nice

6:32 acron^: is there some short hand for this?

6:32 .(map #(str %) (seq "Hello, World"))

6:32 ,(map #(str %) (seq "Hello, World"))

6:32 clojurebot: ("H" "e" "l" "l" "o" ...)

6:34 acron^: ,(split "Hello, World" "*")

6:34 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: split in this context, compiling:(NO_SOURCE_PATH:0)>

6:36 cemerick: ,(map str "hello, world")

6:36 clojurebot: ("h" "e" "l" "l" "o" ...)

6:36 acron^: facepalm

6:36 thanks

6:37 silasdavis: I am getting an arity exception from ((fn [m] ([:li (pretty-message m)])) ({:edge 34}))

6:37 cemerick: you're invoking the map as a function with no arguments

6:37 silasdavis: but fine if I remove the anonymous function and insert the map

6:41 Oh i was trying to evaluate the vector

6:41 and the map

6:55 clgv: how about ##(seq "hello, world")

6:55 lazybot: ⇒ (\h \e \l \l \o \, \space \w \o \r \l \d)

7:09 acron^: clgv: they aren't strings then

7:09 clgv: ahok. didnt know that was a requirement ;)

7:09 acron^: :)

7:10 turns out string/split is probably more suited to my needs anyway

8:05 augustl: what's a good way to do this transformation? https://gist.github.com/4352622

8:07 updated it slightly, the original maps can have multiple keys

8:10 bpr: (reduce #(merge-with conj %1 %2) {} data) seems like a good start

8:11 augustl: oh neat

8:11 bpr: do I really need an initial empty map there?

8:12 bpr: no

8:12 i usually like to put an explicit initial value though

8:13 you may want: (reduce #(merge-with (comp vec flatten conj) %1 %2) data)

8:13 augustl: aww, that gives me (reduce #(merge-with concat %1 %2) queries) yay

8:13 just concat instead of conj

8:13 bpr: depending on your requirements for the values in the resulting map

8:13 augustl: thanks :)

8:13 bpr: oh or that lol

8:14 augustl: :D

8:18 bpr: the concern with concat is that it turns your vectors into lazy-seqs, and then subsequent call to concat will have to walk the entire seq. Not sure if that's what you want

8:18 ro_st: just a sanity check: are jvisualvm/yourkit the best way to profile clojure?

8:18 augustl: bpr: ah

8:19 bpr: ro_st: i'm not a jvm pro, but i do know that this exists: https://github.com/hugoduncan/criterium

8:19 it's a clojure lib for benchmarking your code

8:20 ro_st: thanks, bpr! this looks handy once you've identified hotspots and you're now working to improve them

8:21 bpr: augustl: that said, my solution with flatten also walks the vector each time it's called too

8:21 ro_st: no prob

8:22 augustl: bpr: are there other data structures than vectors that are good for merging?

8:22 ordering doesn't matter so I could use sets

8:22 bpr: yeah, sets could be a good choice

8:22 the concern is the nesting though

8:23 augustl: and then use clojure.set/join probably

8:28 bpr: clojure.set/union

8:28 though i'm thinking there must be a way to accomplish that with vectors

8:31 (reduce #(merge-with (fn [a b] (apply conj a b)) %1 %2) data)

8:32 it's cleaner like this: (reduce #(merge-with (partial apply conj) %1 %2) data)

8:33 augustl: ^ (in case you missed it)

8:34 augustl: ah

8:34 ro_st: partial rocks

9:05 clojure-newb: hi guys, I'm posting a csv file to Compojure with curl, but having trouble getting just the csv data out of an HttpInput… I'm getting all the 'Content-Disposition' and 'Content-Type; info also… how do I extract just the convent of the file ?

9:06 weavejester: clojure-newb: The body of the request is a java.io.InputStream

9:07 ro_st: going to clojurewest, weavejester?

9:07 weavejester: clojure-newb: So you can use clojure.core/slurp, or clojure.java.io/reader with clojure.core/line-seq

9:07 ro_st: Not sure. Maybe not - it's a long way away

9:07 ro_st: cmonnn i'm going, and i'm from Cape Town, South Africa :-)

9:08 clojure-newb: weavejester: thx I'll look into ways to work with an InputStream

9:09 weavejester: ro_st: When is it? March?

9:09 clojure-newb: weavejester: I'm currently doing (slurp (:body req)), and that way I'm getting all the Content-Type stuff I don't want

9:09 ro_st: yes

9:11 weavejester: clojure-newb: What do you mean? The content type is a header.

9:17 clojure-newb: weavejester: I've tried to capture the details in a paste : https://www.refheap.com/paste/7780

9:18 weavejester: I am probably not explaining myself very well

9:18 but I'm trying to just get the csv content in my output

9:18 ro_st: don't need the reader

9:18 weavejester: clojure-newb: No, that paste gives me all the info I need

9:18 ro_st: just (slurp (:body req))

9:19 clojure-newb: what if you (println req) ?

9:19 weavejester: clojure-newb: With curl you're uploading a file as multipart form data

9:19 But you're setting the content-type header explicitly as text/csv

9:19 clojure-newb: ro_st: thx, removed the reader form

9:20 weavejester: You need to first decide whether you're uploading data in multipart format

9:20 clojure-newb: weavejester: so my curl post is kinda mixed up

9:20 weavejester: Or whether you're uploading data directly in the HTTP body

9:21 You're basically saying to curl, upload this as a multipart file, but tell the server it's a raw stream of data

9:21 multipart data can be uploaded through a HTML form

9:21 When you upload a file to a website, that's the format you're using

9:22 The multipart stream also contains information about the file being uploaded

9:22 Such as its content-type (as determined by the client) and the filename

9:22 You can also upload data raw, just by sending the data directly as the HTTP request body

9:22 Without any additional encoding

9:23 clojure-newb: weavejsester: so I am specifying something extra I don't need in my post ? from curl ?

9:23 sorry, a little confused

9:24 weavejester: clojure-newb: The -F option tells curl to send the file as multipart data

9:25 You need to decide whether that's what you want to do

9:25 Put it another way: what is the intended use for this system?

9:25 clojure-newb: weavejester: so I could just do curl -v file=@sample.csv -X POST -H "Content-Type: text/csv" -u user:pass http://host:port/context

9:25 weavejester: clojure-newb: You want the -d option

9:26 clojure-newb: weavejester: initially just to upload small csv files to import data into a system

9:26 weavejester: clojure-newb: So you can send it as a multipart form, using -F file=@sample.csv

9:26 clojure-newb: Or you can send it as a raw data stream using -d @sample.csv

9:26 Ring can handle either, but you need to make a choice :)

9:28 clojure-newb: weavejester: thx for your help, it appears I need to go read up on POST and multipart etc, think I got confused taking it all on in one go

9:29 weavejester: clojure-newb: multipart data is a way of uploading one or more files as form data

9:29 clojure-newb: Usually used in web browsers for uploading files to websites

9:52 clojure-newb: aww, getting close, can anyone help me with extracting and parsing csv content properly ? https://www.refheap.com/paste/7781 - currently my csv lines are being merged after extracting from request body

9:59 bpr: use clojure.data.csv: https://github.com/clojure/data.csv

10:11 WokenFury: any guesses why I'm running into this stackoverflow with Noir?

10:11 Exception in thread "main" java.lang.StackOverflowError

10:11 at clojure.lang.PersistentHashMap.seq(PersistentHashMap.java:194)

10:11 at clojure.lang.RT.seqFrom(RT.java:480)

10:11 at clojure.lang.RT.seq(RT.java:475)

10:11 at clojure.lang.RT.keys(RT.java:503)

10:11 at clojure.lang.APersistentSet.seq(APersistentSet.java:45)

10:11 at clojure.lang.RT.seqFrom(RT.java:480)

10:11 at clojure.lang.RT.seq(RT.java:475)

10:11 at clojure.core$seq.invoke(core.clj:133)

10:11 at clojure.core$set.invoke(core.clj:3643)

10:12 at ns_tracker.dependency$seq_union.invoke(dependency.clj:13)

10:12 at ns_tracker.dependency$transitive$fn__19.invoke(dependency.clj:21)

10:12 at clojure.core.protocols$fn__5871.invoke(protocols.clj:76)

10:12 at clojure.core.protocols$fn__5828$G__5823__5841.invoke(protocols.clj:13)

10:12 at clojure.core$reduce.invoke(core.clj:6030)

10:12 at ns_tracker.dependency$transitive.invoke(dependency.clj:22)

10:12 at ns_tracker.dependency$transitive$fn__19.invoke(dependency.clj:21)

10:12 woops. meant to be a refhjeap link, sorry

10:17 phuff: Howdy.

10:18 I'm making my first clojure project.

10:18 And I want it to have some components that are loaded or not loaded based on a config file of some type, but I'm not sure what the most idiomatic way to do that is in clojure :)

10:18 leinigen just loads clojure files for it's config, and I assume that's the preferred way of doing it.

10:18 But I thought I'd actually ask somebody first :)

10:22 dhm: phuff: can you say more about your goal?

10:22 hyPiRion: phuff: The easiest way is that way, yes.

10:22 Have a map in a file, which you read in at runtime.

10:23 phuff: dhm: So, I'm making a little program that will go and fetch different types of data and make an ebook out of it.

10:23 dhm: And I think different users will want different types of data in their ebooks.

10:23 So I want to make a config file so different users can say: "Use these 5 subcomponents in this order to pull data for my ebook"

10:24 hyPiRion: ,(-> "{:db {:pass \"secret\", :user \"bob\"}}" read-string (get-in [:db :pass]))

10:24 clojurebot: "secret"

10:25 xeqi: phuff: either ENV vars or a config file

10:25 dhm: phuff: well, tbh in that case i would just express the union of all dependencies in leiningen's project.clj and call it a day. i don't think there would be significant savings to conditionally loading them at runtime

10:25 xeqi: I've seen https://github.com/sonian/carica recently for config files

10:25 though I've been using https://github.com/weavejester/environ for the ENV var way

10:25 phuff: dhm: Ah it's not dependencies so much as I need a place to store the things that the user wants

10:25 hyPiRion: dhm: Yeah, I read it that way as first, but the leiningen thing was an example

10:26 phuff: Though I suppose if my program gets really popular (hardy har har) then there might eventually be dependncies.

10:26 But right now it's just "I want to use the following three components that are already part of the program to run the script with"

10:27 (trying to find the part in leiningen's source where they read the project map)

10:27 hyPiRion: phuff: it's easier to read Raynes' Refheap way of doing it

10:27 https://github.com/Raynes/refheap/blob/develop/src/refheap/config.clj

10:28 and https://github.com/Raynes/clj-config

10:28 phuff: Oh that looks neat, hyPiRion

10:28 hyPiRion: It's very easy to use

10:44 Wow, 1.2 certainly is old-fashioned.

10:45 Strange defn-rules

10:47 TimMc: Such as?

10:50 hyPiRion: (defn ^:private foo ...) isn't allowed

10:51 Has to hook it up like (defn foo "docstring" ^:private [params*] ...)

10:54 TimMc: Oh yeah.

11:59 frozenlock: I want to print some stuff to the repl. What I want to print will happen in another thread. Based on the last time I mentioned my problem, it seems that *out* doesn't point to the repl when in another thread. Is there a way to change that?

12:01 When still in swank, all I had to do was to `print' or `println' anything. In nrepl however, it's not the case :(

12:01 hyPiRion: frozenlock: So when you hit up a thread in nrepl and println from it, it won't show?

12:03 You could try bound-fn - which will keep the bindings from where you define the function

12:04 http://kotka.de/blog/2010/05/Did_you_know_IV.html

12:05 frozenlock: That's what I understood from the last time I asked this question. I might be totally wrong... I have a webserver receiving webhooks. In my code I simply have a `print' to send a copy of the webhooks to my repl so I can see live what's being received (I could send to a log-file, but IMO that would defeat the handyness of the repl..). Anyhow, since I moved to nrepl, I can't see anything.

12:05 "Did you know about bound-fn?" Well, no :p

12:06 llasram: frozenlock: This doesn't get you quite where you want, but should help verify the issue --

12:06 frozenlock: If you start the nrepl server via `lein nrepl :headless`, then connect to it

12:06 Er, `lein repl :headless`

12:06 frozenlock: Hmm, rather than nrepl-jack-in?

12:06 llasram: The printed messages should end up on that process's stdout

12:06 Yes

12:07 frozenlock: Let me try that.

12:07 llasram: From emacs just do `M-x nrepl`

12:07 and provide the port the :headless process indicates it is using

12:09 hyPiRion: But yeah, from a web server, the bound-fn trick is probably hard to use without modifying the router and thread scheduler manually.

12:09 I haven't looked at it though, so may be easier than what I anticipate.

12:09 silasdavis: What's the best way to dispatch in a functin depending on whether I get a single item or a collection?

12:10 frozenlock: No, nothing showing up.

12:10 hyPiRion: silasdavis: ##(if (coll? [1 2 3]) :coll :no-coll)

12:10 lazybot: ⇒ :coll

12:11 hyPiRion: If it's only a yes/no thing then that's the simplest to process for us humans.

12:11 frozenlock: what are you using? compojure?

12:11 frozenlock: silasdavis: you might want to look `seq?'

12:12 hyPiRion: Noir... I'll switch to compojure after this. But it uses compojure in the background IIRC.

12:13 llasram: frozenlock: Huh. Nothing showing up on the process stdout?

12:13 hyPiRion: ,(map (juxt identity seq? coll?) ['(:list) [:vector] {:a :map} #{:set}])

12:13 clojurebot: ([(:list) true true] [[:vector] false true] [{:a :map} false true] [#{:set} false true])

12:14 hyPiRion: mm.

12:14 frozenlock: Nothing in eshell (where I started lein repl :headless), nothing in my *nrepl*, nor in *nrepl-connection*.

12:14 hyPiRion: What a tease. =|

12:15 * frozenlock seems to have lost his stdout

12:17 frozenlock: hyPiRion: I just discovered pmap with your link, thanks :)

12:17 mthvedt: in core.clj, calling (concat) returns (lazy-seq nil)

12:17 why lazy-seq?

12:19 hyPiRion: I suppose it's because concat says it will lazily merge the lists it receives

12:20 ,(map class [() nil (concat)])

12:20 clojurebot: (clojure.lang.PersistentList$EmptyList nil clojure.lang.LazySeq)

12:20 mthvedt: ,(type (concat))

12:20 clojurebot: clojure.lang.LazySeq

12:20 llasram: frozenlock: At least for me, I'm able to verify that the root binding for *out* writes to stdout: (binding [*out* (.getRawRoot #'*out*)] (println "goes where?"))

12:20 mthvedt: maybe it's to not break things that always expect a lazy seq

12:20 hyPiRion: mthvedt: yeah, I suppose it is.

12:21 ppppaul: i want to do HTTP mocking/DI in clojure... any ideas?

12:21 llasram: frozenlock: Do you get output with that?

12:21 technomancy: ppppaul: requests or responses?

12:22 frozenlock: llasram: yup

12:22 OMG

12:22 llasram: Well then. I have absolutely no idea into what limbo your other lines are going

12:22 frozenlock: stupid stupid stupid stupid stupid stupid stupid

12:23 When I did what you asked it showed all the received webhooks. Guess I wasn't flushing the lines...

12:23 ppppaul: response mocking

12:23 technomancy,

12:24 technomancy: ppppaul: have you tried using with-redefs on your HTTP client defns?

12:24 llasram: frozenlock: Oh! I wonder if running under eshell is affecting flushing behavior

12:24 ppppaul: technomancy, i haven't tried anything yet cept doing some google searching on http mocking with clojure

12:24 hyPiRion: llasram frozenlock, yeah, eshell != terminal when it comes to flushing

12:24 at least with java

12:25 llasram: Ah, probably not providing it with a pty

12:25 frozenlock: Wow, thanks so much guys! It's aliiive!

12:25 technomancy: eshell doesn't affect flushing

12:25 unless your java code is checking for TERM=dumb and special-casing it or something

12:25 frozenlock: I think my mistake was to use print instead of println

12:26 llasram: Oh! Well there we go then

12:26 Hmm. So: should nrepl servers alter-root-var to make make the root binding of *out* be the REPL output buffer?

12:28 technomancy: I added that to swank

12:28 ppppaul: technomancy, with-redef looks cool

12:28 technomancy: ppppaul: 90% of the time people ask mocking questions, the answer is with-redefs

12:29 a common pattern is to close over an atom and redef the function in question to #(swap! received-atom conj %&)

12:29 then once the code in question is run, the atom contains all the args the function has been called with

12:30 ppppaul: interesting

12:30 i haven't used atoms yet

12:30 technomancy: most people go wandering off looking for a "mocking framework" when everything they need is staring them right in the face

12:30 ppppaul: haven't used swap either

12:30 technomancy: they go hand in hand

12:30 ppppaul: can i only redef vars that i can see?

12:31 can i redef a var in a lib that isn't exposed?

12:31 technomancy: try it and see

12:31 ppppaul: ok

12:31 :)

12:31 have you heard of midje?

12:32 technomancy: yes

12:33 ppppaul: thoughts?

12:34 technomancy: I don't think it offers much advantage over clojure.test

12:35 bpr: ppppaul: a lot of people who know more about clojure than i do seem to like it. I don't b/c it does a lot of "magic" with redefining vars and so forth that often breaks for me.

12:36 llasram: ppppaul: I use it for testing Cascalog queries, but actively dislike its "tests run when loading the test namespace" model. It makes it fiddly to have helpers specific to a test namespace

12:36 technomancy: urgh; does it really have side-effects at load time?

12:36 ppppaul: hmmm interesting

12:37 * technomancy shifts his recommendation from "meh" to "actively avoid"

12:37 ppppaul: lol

12:37 hyPiRion: I suppose it's good for TDD

12:38 ppppaul: technomancy, can you comment on weather this is a good example of using with-redefs to mock? https://gist.github.com/4354264

12:38 hyPiRion: But I'm usually testing to check that the design of the library I design is okay

12:38 It's good to find code smells.

12:39 technomancy: ppppaul: with-redefs-fn is lower-level; use with-redefs instead

12:39 ppppaul: typically in a real test you would want to store the value in an atom where you can check it later rather than printing it, but for interactive use printing is fine

12:39 ppppaul: the only examples i have are at http://clojuredocs.org/clojure_core/clojure.core/with-redefs those any good?

12:40 technomancy: yeah that looks reasonable

12:40 ppppaul: ^_^

12:41 ghadishayban: try this in your repl: (def ^{:foo (println "HA")} bar 42)

12:41 ppppaul: ##(def ^{:foo (println "HA")} bar 42)

12:41 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

12:42 TimMc: Interesting.

12:42 So, we've seen metadata get eval'd 0, 1, and 2 times.

12:42 ghadishayban: I just fixed it on CLJ-1137

12:42 yeah

12:42 interesting follow up to last night

12:43 DaReaper5: How do i check {"derp" true} for the existence of the key "herp"

12:43 TimMc: DaReaper5: contains?

12:43 DaReaper5: contains? is throwing null pointer error

12:44 hmm this might be stupid but if i have nothing set for the else for an "if" that should nto cause an issue

12:44 TimMc: ,(contains? {:a 5} :a)

12:44 clojurebot: true

12:44 ghadishayban: ##(let [^{unresolved mysteries} foo 42] foo)

12:44 lazybot: ⇒ 42

12:45 TimMc: DaReaper5: (if x y) is the same as (if x y nil) (or (when x y))

12:45 ghadishayban: ##(let [^{:key (throw (Exception. "hurt me"))}  foo 42] foo)

12:45 lazybot: java.lang.RuntimeException: Unable to resolve symbol: foo in this context

12:45 ghadishayban: oh strange

12:45 technomancy: ghadishayban: clojure doesn't treat non-breaking spaces right IIRC

12:45 " foo"

12:45 I opened a bug for it and it was wontfix'd

12:46 TimMc: ,(let [^{:key (throw (Exception. "hurt me"))} foo 42] foo)

12:46 clojurebot: 42

12:46 TimMc: technomancy: That's rather infuriating.

12:46 DaReaper5: http://pastebin.com/m1zdctfM

12:47 there is a snipit of my code

12:47 (simplified kinda)

12:47 TimMc: clojurebot: nbsp is http://www.trygve.com/doomsday.html

12:47 clojurebot: c'est bon!

12:47 technomancy: TimMc: I had a ridiculous hack that was foiled by that bug involving problems in cygwin's escaping and using clojure.main -e with an arg that cygwin would parse as a single token but Clojure would parse as multiple

12:47 TimMc: Oh yeah, I think I remember that. Horrifying.

12:48 DaReaper5: TimMc (contains? {"derp" true} "display") is causing my error

12:48 :/

12:48 TimMc: ,(contains? {"derp" true} "display")

12:48 clojurebot: false

12:48 TimMc: Not by itself it isn't.

12:49 ,(->  foo quote name count)

12:49 clojurebot: 4

12:49 DaReaper5: http://pastebin.com/3EjtEZ8n

12:50 hmm i might have an idea

12:50 if false then does the if return null

12:50 hyPiRion: Yeah, those spaces man

12:50 ,(let [a 10, a 9] {a 1, a 2})

12:50 clojurebot: {10 1, 9 2}

12:50 xeqi: any recommendations on a full text search library?

12:50 TimMc: hyPiRion: AAAAGGGHHH

12:51 hyPiRion: TimMc: ?

12:51 TimMc: DaReaper5: Check my message of 6 minutes ago.

12:51 DaReaper5: TimMc i have only been here for like 3 min

12:51 i see now

12:52 dam

12:52 TimMc: hyPiRion: Somehow that was even more visually terrifying than the example I posted.

12:52 hyPiRion: I have this lovely Norwegian keyboard, which contains the key "Alt Gr". Whenever I hit that one and space simultaneously, I get these lovely spaces all over. It's a complete mess to debug too.

12:53 technomancy: http://dev.clojure.org/jira/browse/CLJ-419

12:53 DaReaper5: TimMc is there a way i can specify the if on else to do absolutly nothing?

12:53 not even pass null?

12:53 TimMc: hüÖíËíóñ° Í há®é ñó íðéá åháþ üóú´ëé þáøœíñg ábóúþ. °¥

12:53 technomancy: xeqi: other than lucene you mean?

12:53 DaReaper5: i think the null being passed is fucking up my parent method

12:53 ... which is actually just a sql query builder

12:54 TimMc: DaReaper5: It's an expression, just like (almost?) everything in Clojure. It has a return value. What shall the return value be?

12:54 xeqi: technomancy: as in I know very little about fts other then lucene,solr,and such exists

12:54 and easy ways to use it from clojure / score things

12:55 TimMc: hyPiRion: ^ my keyboard is set up with an AltGr as well.

12:55 jkkramer: xeqi: I think elasticsearch or solr are the go-to solutions these days

12:55 xeqi: there's an elasticsearch clojure lib

12:55 technomancy: xeqi: lucene is pretty much the gold standard in the industry for full-text search

12:55 hyPiRion: TimMc: ←↓→ :D

12:56 technomancy: solr and elasticsearch are just ways of making lucene indices that span multiple machines

12:56 "just"

12:56 hyPiRion: It's handy for those times i need a µ or a π without going to a character map

12:56 TimMc: Hmm, AltGr + space doesn't give me U+00A0.

12:56 hyPiRion: Which is possibly once a year.

12:56 TimMc: lucky bastard

12:57 technomancy: M-x ucs-insert

13:10 hyPiRion: I find myself using (fn [a b] (f (g a) (g b))) quite often, is there a function within core which takes f and g and produces such a fn?

13:10 technomancy: I bet useful has something

13:11 hyPiRion: Right, I'll have a peek there. Though I don't like to depend on such a huge set of fns for such a small thing.

13:11 Oh well

13:13 ppppaul: technomancy, i'm running my project off a SAAS and they want me to go back to lein 1.7 instead of 2 (which is what i'm developing on)... any thoughts? seems like a pain to go back to 1.7 since plugins are installed differently and my project file would need to be changed.

13:18 technomancy: ppppaul: 1.7 is pretty outdated. who is it that's stuck on it?

13:19 DaReaper5: TimMc ok i know exatly my issue right now, a third party library i am using cannot except nil.

13:20 I am trying to check a value and if it exists then i indicate a field to be used in a query

13:20 either i need a way of check and doing absolutly nothing if it does not exist

13:20 or i need a way of building an array

13:21 but i cant do that because data structure are immutable

13:21 Here is what i want to do in plain english: "If field exists, include/use field name"

13:27 ppppaul: technomancy, vmfarms. they aren't used to clojure

13:28 they think that 1.7 is the latest stable branch

13:30 technomancy: ppppaul: that's a technicality. if it helps you can send them to https://github.com/technomancy/leiningen/commit/14f566bd5738cba44e692131fb81cdfbc67f28b2#L1R83

13:32 or you can tell them I said they're wrong =)

13:33 also relevant is that the only mention of 1.x on leiningen.org is a link titled "Still using 1.x?"

13:35 ppppaul: thanks a lot :)

13:48 bpr: technomancy: i'm glad you mentioned the "useful" library earlier. I'd never heard of it, and it contains some really cool stuff.

13:52 technomancy: yeah lots of good stuff in there

13:53 amalloy_: are there docs for it?

13:57 hyPiRion: It's hard to dig through to try and find the fns you need

13:57 Or well, it's not apparent

14:09 unlink: Is there a function/macro which is like: (fn [x & rest] x) i.e. that discards all arguments but the first (for side effects)

14:12 llasram: unlink: Oh, like Scheme/CL `prog1`? AFAIK there isn't one in the Clojure standard library, no

14:13 wtf, CL has `prog2`? When would you ever want that?

14:15 daimrod: llasram: retro-compatibility with older lisp dialects I guess.

14:17 technomancy: unlink: comp first list maybe?

14:18 unlink: if you want a macro try doto

14:20 unlink: yeah, prog1 is what I want, not doto.

14:20 thanks.

14:24 technomancy: huh; apache's sshd is still maintained

14:24 though its web page has no CSS applied

14:26 mehwork: anyone know why clojure would give me the error: Exception in thread "main" java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String ?

14:26 in a repl i clearly can convert a long to a string

14:26 ,(str 1)

14:26 clojurebot: "1"

14:27 amalloy: technomancy, hyPiRion: not much comprehensive documentation for useful. i'm not sure how you would document "a collection of utility functions" any better than listing all the function names and docstrings which, of course, is in the source already

14:28 technomancy: amalloy: ns-level docstrings?

14:29 amalloy: (ns ^{:doc "Functions for working with maps"} useful.map)?

14:29 anyway, if (fn [f g] (fn [a b] (f (g a) (g b)))) were in useful it would be in useful.fn, but i don't think it is

14:29 technomancy: at least use proper docstring syntax =)

14:30 llasram: mehwork: That's not the same thing. ##(symbol (str 1))

14:30 lazybot: ⇒ 1

14:30 llasram: mehwork: That's not the same thing. ##(symbol 1)

14:30 lazybot: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String

14:30 llasram: Er, didn't mean to repeat "not the same thing" twice

14:30 But you get the idea

14:31 mehwork: Something which ultimately calls a java method expecting a particular type will throw a ClassCastException when getting the wrong type

14:31 hammer: this has to be so easy: how do i re-run my last statement in counterclockwise?

14:32 (yes, i tried hitting up arrow)

14:33 TimMc: hammer: Hmm, try ctrl-up?

14:33 Or C-p I guess.

14:33 hammer: haha

14:33 mehwork: llasram: interesting

14:33 hammer: the ctrl -> command switch is still getting me

14:33 jlr: I'm curious enough to ask this cursorily now, but a full discussion will require a forum post... given the experience implementing ClojureScript, how plausible would it be to follow the same model but make Emacs Lisp the direct host of the language - rather than an extension language akin to pymacs or even guile, making it as easy as doing (require 'cl) and using the clojure interop style to call elisp functions?

14:33 hammer: (inc TimMc)

14:33 lazybot: ⇒ 28

14:33 TimMc: hammer: Was C-up?

14:33 hammer: ctrl + up worked

14:34 technomancy: jlr: you would have to choose between seamless interop with existing elisp mutable types and having a proper equality predicate

14:34 the two are mutually exclusive

14:34 TimMc: technomancy: No 2.x release yet?

14:34 jlr: ah, that's unfortunate

14:34 technomancy: jlr: I blogged more about it here: http://technomancy.us/159

14:34 jlr: obviously everyone would love a Clojure based Emacs

14:35 thank you for the link, I will certainly read it

14:35 technomancy: TimMc: no, library maintainers aren't pushing their libs to the clojars releases repo

14:35 slackers

14:35 jlr: Of course you and the other Relevance people have contemplated it already ;)

14:35 TimMc: technomancy: How does that block lein 2.x?

14:35 technomancy: I'm not a relevance guy

14:35 brainproxy: jlr: have you seen the deuce project?

14:35 jlr: oh, I thought you were

14:36 technomancy: nah I work for Heroku

14:36 TimMc: jlr: They *should* pay him.

14:36 jlr: I know who you are. Just assumed since you're one of the fundamental members of the community, you were part of relevance *laughs*

14:36 I would certainly agree. For lein and many many other contributions.

14:36 (TimMc)

14:37 technomancy: jlr: I don't actually work on Clojure itself

14:37 jlr: brainproxy: no, I'll google it.

14:37 I consider your contributions to its ecosystem very much fundamental :) But not Clojure itself eh? Interesting. Well your tools are great.

14:37 technomancy: TimMc: everything will break if people start dropping the clojars snapshots repo before the releases repo is populated

14:37 brainproxy: jlr: https://github.com/hraberg/deuce

14:38 "emacs under clojure"

14:38 TimMc: technomancy: Hmm, not familiar with this.

14:39 technomancy: IMO deuce goes the wrong way; there's too much existing code out there building on the quirks and undocumented behaviour of the existing elisp runtime for moving it to a new one to be feasible

14:39 jlr: Ah ha. I had thought about this too at one point. Could you replace the C part of Emacs and just write a full elisp interpreter/compiler in Clojure and somehow succeed at that. I wonder if you could 'wall off' elisp into its own mutable world and then extend with clojure from where we are onward

14:39 technomancy: jlr: some people think it's possible and are trying to do it with Guile (which does have immutability)

14:39 jlr: (brainproxy. sorry - will address nicks properly. It's early)

14:40 Well, you guys are the ones who can if anyone can. I'm not up to that sort of level this early in my career.

14:40 technomancy: that effort is much more likely to succeed than a version on Clojure, but I think the odds of it actually being able to run extant elisp libraries are very slim

14:41 jlr: It's such a tough thing, there's such a vast amount of Emacs in Emacs that reimplementation in full form seems crazy. But if we could get a more Genera-style environment with graphics+text but follow the Emacs way... Something so incredible could be built with this language.

14:41 brainproxy: technomancy: yeah, i'm not sure deuce will actually succeed to any degree, but I was just pointing out to jlr that such a project exists

14:41 TimMc: technomancy: Found it: https://groups.google.com/forum/?fromgroups=#!topic/clojars-maintainers/d8HNd-R4uw8

14:41 technomancy: jlr: people have tried to hoist it onto the CL runtime several times and they never got anywhere

14:41 jlr: I wonder what it would actually take financially to pay a few people to work full time to translate existing elisp libraries to Clojure like crazy, to tool up a new reimplementation of Emacs with enough stuff to pull people over

14:42 technomancy: I've read about those efforts. It's a tough thing for sure, people keep taking stabs at it and not succeeding

14:42 technomancy: a clj->elisp compiler would be much less work, but you'd have to add immutable lists and strings to the Emacs runtime first

14:43 immutable strings in emacs are not completely out of the question according to the maintainers.

14:43 I've asked them about it and apparently it wouldn't break much

14:43 immutable lists are way harder

14:43 plus elisp doesn't really have the means of abstraction to do a proper self-hosted thing

14:43 frozenlock: technomancy: any chance to see immutable strings in the next.. 2 years?

14:43 jlr: As I think of it - given what was done with Climacs, trying to do something sort of akin to that - custom GUI from scratch done the Clojure way, up to the point of an Emacs-like editor in Clojure - plus translation of a few hundred major elisp libs to Clojure... Do you have any thoughts about what that would take to pay to make happen? Could it be kickstartered?

14:44 technomancy: frozenlock: it's never going to happen unless someone really cares about it and pushes through on it. and that someone would have to know C.

14:44 jlr: Hire a few of the best, maybe even try to get Relevance and Rich himself to consult some

14:45 technomancy: it's a lot of work for little benefit; without immutable lists it's not really that valuable

14:45 jlr: there was a summer of code proposal for that, but it wasn't accepted

14:45 jlr: wow, that's sort of a tragedy..

14:46 technomancy: I don't think it's a good idea

14:46 jlr: I still think given what we saw with Light Table it's not out of the question to kickstart it

14:46 really?

14:46 technomancy: you're never going to come close to competing with emacs for breadth of available libraries

14:47 frozenlock: Without counting everyone's personal code...

14:47 technomancy: who's going to port magit, org-mode, gnus, etc?

14:47 gnus itself is larger than any public OSS clojure project in existence

14:47 jlr: I guess my image of it is to be more expansive, move emacs towards having more graphical command-line like qualities, interactions you can't do now, and just everything you could do if you wrote Emacs now

14:47 technomancy: and that's just a tiny slice of what's out there

14:47 jlr: Oh my gosh, they're that big, I see

14:48 ohpauleez: and it's going to introduce another barrier for adopting Clojure- "I have to learn this new editor if I want the best support?"

14:48 jlr: I mean my own dot-emacs is like 4k lines so I understand, but I'd hoped if you reach critical mass people would see it as worth the effort

14:48 Ah, good point as well

14:48 ohpauleez: Nonethelss, writing an editor is a great learning experience

14:48 so if you're interested, totally go for it!

14:48 technomancy: it's an inconceivably huge amount of effort for a tiny community like clojure

14:49 jlr: I lack anything resembling the technical skill to succeed at writing a new Emacs ;)

14:49 I see. Well, perhaps some day.

14:49 technomancy: writing just an editor of course is feasible

14:49 jlr: Thanks for all that

14:49 technomancy: but you're talking about an entire OS

14:50 jlr: Exactly - an entire OS is precisely what I want, in Clojure. Heh. Yes, that is getting ahead of ourselves by a few years...

14:57 Netfeed: what's the best way to convert something like f(x) = x + x to something like (defn f [x] (+ x x))?

14:58 frozenlock: Netfeed: if it's for math/analytics stuff, incanter allows you to use infix notation

14:59 Netfeed: nono, parsing text

14:59 dnolen: Netfeed: write a parser?

14:59 Netfeed: or use an existing Clojure parser - there are a few

15:00 Netfeed: alright

15:00 frozenlock: Big move... from Noir to compojure. Any advices/tutorials?

15:01 technomancy: frozenlock: did you see the refheap port raynes posted?

15:01 frozenlock: Looking at it now in fact.

15:05 bosie: does anyone have a lib/idea how to detect binary files?

15:05 or rather: a tool detecting html files?

15:05 frozenlock: *.html :-)

15:06 bosie: frozenlock: i don't have the filename ;)

15:06 amalloy: bosie: just use the unix `file` command

15:07 bosie: amalloy: that seems a bit counterproductive, no?

15:07 amalloy: in the sense you can't run it on windows anymore

15:07 bpr: i'd call that productive lol

15:08 bosie: haha

15:09 TimMc: There's always Apache Tika, I guess.

15:09 I think it uses the same database as file.

15:10 bosie: hm

15:13 TimMc: echo "MOVIE REVIEWS" | file - ## /dev/stdin: Silicon Graphics movie file

15:13 lazybot: "MOVIE REVIEWS" | file - ## /dev/stdin: Silicon Graphics movie file

15:13 TimMc: Good times.

15:15 Except some bloopers.

15:15 *Expect

15:18 amalloy: for some reason, TimMc, i never imagined `file` could take input from stdin, even though i knew it only used the file's contents. i was like "well duh, you're asking what kind of file something is, so it has to be a file"

15:18 tgoossens: i keep using loop and recur for infinite loops in a thread. is there a better way. I'm kinda feeling bad about how i'm doing it now

15:20 llasram: tgoossens: Over what are you looping infinitely?

15:20 AimHere: ,(loop [] (recur))

15:20 clojurebot: Execution Timed Out

15:21 tgoossens: it is still an unfinished function : https://gist.github.com/4355451

15:21 experimenting

15:22 llasram: tgoossens: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html

15:23 frozenlock: tgoossens: at-at from overtone https://github.com/overtone/at-at

15:23 tgoossens: interesting

15:24 damnit! you/myself caught me again. On the fact that I did not search for existing solutions for that "rate" stuff

15:24 at at looks cool

15:24 llasram: frozenlock: Oh, nice. I like the REPL-friendly aspect

15:26 tgoossens: i should really train myself to sometimes stop, look at what i want to do, and search for similar / same problems and solutions

15:26 frozenlock: 20s on IRC can save weeks of development

15:26 tgoossens: yes

15:26 funny though

15:27 today a book arrived that i ordered

15:27 "how to solve it"

15:27 polya

15:28 bbloom: tgoossens: that top level loop isn't required

15:28 tgoossens: it addresses exactly the thing i just experienced

15:28 bbloom: functions are themselves loop targets

15:29 ,(fn [] (recur))

15:29 clojurebot: #<sandbox$eval53$fn__54 sandbox$eval53$fn__54@58ab3daf>

15:29 tgoossens: bbloom: can you recur on that?

15:29 bbloom: ,((fn [] (recur)))

15:29 tgoossens: ah yes

15:29 clojurebot: Execution Timed Out

15:29 tgoossens: i see what you mean

15:30 bbloom: also, when-not's body is an implicit do, so you don't need the do either

15:30 (doc when-not)

15:30 clojurebot: "([test & body]); Evaluates test. If logical false, evaluates body in an implicit do."

15:30 tgoossens: wow

15:30 bbloom: that's the whole point of when vs if

15:30 tgoossens: ,(doc when)

15:30 clojurebot: "([test & body]); Evaluates test. If logical true, evaluates body in an implicit do."

15:31 tgoossens: mmyes

15:31 lol

15:31 this is getting embarrassing :p

15:31 bbloom: other than that: there's nothing wrong with an infinite loop for a simulation

15:31 that's how simulations work!

15:31 and tail recursion is the clojure way of looping

15:34 nDuff: ...well, _one_ clojure way of looping. :)

15:34 There's also iterating over infinite lazy sequences.

15:34 ...which I'd argue is actually more clojure-y

15:36 tgoossens: bbloom: btw this is the context (namespace) where that function is

15:36 https://github.com/tgoossens/robotclj/blob/master/src/robotclj/virtual.clj

15:37 its a first experiment. i'm still far from sure how i want to create the simulator

15:37 just playing aroud

15:37 *around

15:37 bbloom: tgoossens: nitpick: most clojure code uses 2-space indents instead of tabs

15:37 tgoossens: blloom: i know. But for some reason when i push it to git. it is screwed up

15:38 bbloom: ....what? that seems unlikely heh

15:38 tgoossens: in my sublimetext editor it looks fine

15:38 (2 spaces)

15:39 bbloom: tgoossens: (fn [simulator] false) -> (constantly false)

15:40 why does your multimethod return functions?

15:40 why not take the simulator atom as an argument? you can dispatch on the :type of the second argument

15:41 er rather take the simulator *value* as an argument

15:41 and return the new value

15:41 tgoossens: bbloom: this is what happend. I wanted a map from command-> action. but a simple hash-map did not suffice. So I found out that i could do what i want with multimethods: binding to a command a function

15:42 mpan: would it be a good/bad idea to use zippers for an implicit search tree that isn't actually modifiable?

15:42 bbloom: why didn't a hash-map suffice?

15:42 tgoossens: a command is {:type ::drive :other keys}

15:42 bbloom: ah.

15:42 tgoossens: i needed a function based on the type

15:43 bbloom: i have a thing for this :-) https://github.com/brandonbloom/dispatch-map

15:43 tgoossens: ah. yes. i remember reading that on planet clojure

15:43 bbloom: but in reality, a multimethod is probably fine for what you need

15:43 tgoossens: i think i commented on the blogpost asking whether you don't lose "exentability"

15:43 *extendability

15:44 bbloom: ah

15:44 tgoossens: was that you?

15:44 bbloom: that's me

15:44 tgoossens: aight :)

15:44 cool

15:45 bbloom: i'm just not sure why your multimethod has 3 levels of indirection: the method, the (fn [simulator] ...) and then the :*-fn

15:45 seems like you could collapse those all down

15:46 tgoossens: hmmm maybe. but i wanted was a mapping from command type to function. and then be able to still pass that function around (not executing it immediately)

15:47 bbloom: i see

15:47 tgoossens: i'll be back in a minute. then i'll explain my intends with the simulator abit

15:49 ppppaul: is it possible for me to call private functions?

15:50 bbloom: ppppaul: private vars are callable: (#'the-ns/private-fn 1 2 3)

15:50 ppppaul: cool

15:50 ynniv: I would like to use korma's query dsl, but korma really wants to bring along its friends. is there a way to make this happen, or another project that only generates query strings?

15:51 amalloy: $google lein dependency xclusions

15:51 lazybot: [technomancy/leiningen · GitHub] https://github.com/technomancy/leiningen

15:51 amalloy: well, typo. anyway, check the sample project.clj for exclusions

15:51 TimMc: amalloy: I hadn't considered before either. I just wanted a really short example, and "-" *usually* works with GNU utils...

15:52 amalloy: well, usually - is optional

15:52 TimMc: In this case it is required, apparently.

15:53 ynniv: amalloy: is that a reply to me? I'm already excluding deps, but korma statically loads things that I don't want

15:53 amalloy: you're out of luck, then

15:53 TimMc: - appears to be an undocumented option to file.

15:54 tgoossens: bbloom: ok https://github.com/tgoossens/robotclj/blob/master/src/robotclj/core.clj

15:54 this will be the "dispatching" part

15:54 i need to send commands like, drive, turn, explore maze, to either a virtual robot or a remote (bluetooth) nxt robot

15:55 so for the simulator case, it will have to create commands and send it to the simulator

15:56 i'm still not sure whether i should use an atom, agent for the simulator (currently i'm opting for an atom because i need to be able to stop the robot immediately, but an agent reflects maybe better reality)

15:56 in the simulator there is a key ":command" that contains the command (to be) being executed in the simulator

15:58 the simulator must start executing the command as long as the stopcondition returns false.

15:58 Or it should start executing another command if it gets swapped

15:59 bbloom: thats the general idea

16:00 mehwork: how can i conver a list like '("a","b","c") into strings as separate args that i can pass to a function: "a" "b" "c"

16:00 dnolen: mehwork: apply

16:00 (apply f some-list)

16:00 mehwork: although, if [& args] puts them back in a list i don't know why i can't just pass it as a list

16:00 thanks i'll try it

16:01 dnolen: ,(str "a" "b" "c")

16:01 AimHere: Well how would the function know that you wanted to pass a list of arguments, rather than a list as your first argument?

16:01 ynniv: yeah, annoying to work around what seems to be unnecessary destructuring

16:01 clojurebot: "abc"

16:01 dnolen: ,(apply str (list "a" "b" "c"))

16:01 clojurebot: "abc"

16:02 mehwork: i don't want them to become a single string

16:02 dnolen: mehwork: I know, it's just an example

16:03 mehwork: i think the prob is that "a" "b" "c" is a concatentation on a string, so it's the same as saying "abc"

16:03 TimMc: mehwork: It's not.

16:04 mehwork: there needs to be the opposite where it splits "abc" to "a" "b" "c"

16:04 oh you're right nm

16:04 i guess that's only if you print it

16:04 er

16:04 what the heck it was just happening, now it's not :/

16:05 seangrove: ,(type (str "a "b "c))

16:05 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.RuntimeException: EOF while reading string>

16:05 mehwork: oh that does a b c

16:05 seangrove: ,(type (str "a "b "c"))

16:05 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: b in this context, compiling:(NO_SOURCE_PATH:0)>

16:05 seangrove: hah

16:05 ,(type (str "a" "b" "c"))

16:05 clojurebot: java.lang.String

16:06 TimMc: ,(str)

16:06 clojurebot: ""

16:14 mehwork: is there a way to convert a sequence ["a","b","c"] to just "a" "b" "c"?

16:15 technomancy: mehwork: that question doesn't really make sense

16:16 mehwork: technomancy: well i want to pass a variable list of arguments dynamically

16:16 bbloom: (doc apply)

16:16 clojurebot: "([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."

16:16 technomancy: oh, during function application specifically?

16:16 yeah, that

16:16 mehwork: ok i guess i need to play with apply more, i couldn't get it to work yet

16:17 technomancy: ,(apply str "a" "b" ["c" "d" "f"])

16:17 clojurebot: "abcdf"

16:18 mehwork: yeah that's all i can ever get it to do which isn't what i want because i want to do (myfunc <expand '("a" "b" "c") args>) and have it act as though i typed: (myfunc "a" "b" "c")

16:18 3 sep args, not 1

16:19 technomancy: apply only does its magic on the last argument

16:19 seangrove: Almost ready for our new release - 99% clojurescript: http://dl.dropbox.com/u/412963/zenbox/zenbox_preview_jan.mov

16:19 bbloom: ,(apply str (concat '("a" "b" "c") [1 2 3]))

16:19 clojurebot: "abc123"

16:20 seangrove: Just a tiny bit of glue javascript here and there, but overall extremely happy with clojurescript for production apps

16:20 mehwork: i feel stupid because i'm just not getting what you're saying :[

16:20 bbloom: mehwork: read the doc string for apply again

16:21 amalloy: bbloom: the docstring for apply is not instructive at all

16:21 bbloom: then consider this function (fn [& args] (count args))

16:21 ((fn [& args] (count args)) 1 2 3)

16:21 ((fn [& args] (count args)) 1 2 3),

16:21 dammit:

16:21 seangrove: hah

16:21 bbloom: ,((fn [& args] (count args)) 1 2 3)

16:21 clojurebot: 3

16:21 bbloom: ,(apply (fn [& args] (count args)) 1 2 [3])

16:21 clojurebot: 3

16:21 bbloom: ,(apply (fn [& args] (count args)) 1 2 [3 4 5])

16:21 clojurebot: 5

16:21 bbloom: ,(apply (fn [& args] (count args)) 1 2 [3 4 5] 6)

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

16:21 bbloom: ,(apply (fn [& args] (count args)) [1 2] [3 4 5])

16:21 clojurebot: 4

16:21 dnolen: mehwork: apply does what you want - give us an example (paste) where it's not working for you.

16:22 bbloom: does it make sense now?

16:22 mehwork: no but i'm playing with it in a repl till it does

16:23 bbloom: better yet: (fn [& args] args)

16:23 hyPiRion: when apply is given more than one arg, all but the latter is considered as singletons

16:23 bbloom: ,((fn [& args] args) 1 2 [3 4 5])

16:23 clojurebot: (1 2 [3 4 5])

16:23 bbloom: ,(apply (fn [& args] args) 1 2 [3 4 5])

16:23 clojurebot: (1 2 3 4 5)

16:23 bbloom: ,(apply (fn [& args] args) [1 2] [3 4 5])

16:23 clojurebot: ([1 2] 3 4 5)

16:23 bbloom: seangrove: neat. some kind of CRM tool?

16:23 mehwork: o wait

16:24 seangrove: bbloom: Kind of a meta-crm tool, yeah

16:24 bbloom: read

16:24 er wrong window

16:25 seangrove: It fits in gmail like rapportive, or anywhere on the web where you hover over an email, and it'll pull in all of the data you have on that email from Salesforce, Mailchimp, Stripe, your database, and ~25 others

16:25 bbloom: seangrove: sounds interesting

16:26 gonna write up a cljs success story? :-)

16:26 mehwork: does apply not work on normal lists?

16:26 dnolen: mehwork: it does

16:27 seangrove: bbloom: Yeah, this has been a complete re-write from js/jQuery -> cljs/Closure. There'll be a post on the UI design changes in the product, and another on the technical changes to cljs

16:27 Both are reasonably interesting in hindsight

16:28 bbloom: seangrove: looking forward to them

16:28 mehwork: ,(apply (fn [& args] (count args)) ("a" "b" "c"))

16:28 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

16:29 mehwork: ,(apply (fn [& args] (count args)) '("a" "b" "c"))

16:29 clojurebot: 3

16:29 mehwork: ahhh now i get it

16:31 dnolen: mehwork: though that issue really has nothing to do w/ apply

16:32 ,("a" "b" "c")

16:32 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

16:32 jro_: do yo write unit tests in your clojure development? or quickcheck style testing?

16:33 mehwork: jro_: what's quickcheck style?

16:33 ppppaul: when i set my :test-paths ["test"] in project.clj i get an error-> lein test

16:33 Error loading project.clj

16:33 mehwork: like manually running it to see if it seems to be working?

16:34 ppppaul: anyone able to point me to a url that'll help me get 'lein test' working on my project?

16:34 jro_: combinatorial testing, like Haskell's QuickCheck. ClojureCheck seems to be similar

16:34 technomancy: ppppaul: :test-paths defaults to ["test"]; no need to add it

16:35 weird that you're getting an error though; works here

16:35 dnolen: jro_: there's also the test.generative contrib library

16:35 ppppaul: when i omit that line i get Exception in thread "main" java.io.FileNotFoundException: Could not locate clojure_api/core_test__init.class or clojure_api/core_test.clj

16:35 technomancy: jro_: most people just use regular clojure.test by a fairly wide majority

16:40 tgoossens: bbloom: your dispatch-map works great

16:41 ppppaul: when testing clojure do i have to call all my tests from core_test.clj?

16:41 bbloom: tgoossens: nice! :-)

16:41 tgoossens: still figuring out how to pass use the other fields of the command

16:41 (like my multimethod)

16:41 technomancy: ppppaul: you can scatter deftest forms all over your test/ directory as you like

16:41 ppppaul: maybe it'd be helpful to look at an existing project as an example

16:43 tgoossens: bbloom is it even possible?

16:43 ppppaul: that could be helpful

16:43 bbloom: tgoossens: is that possible?

16:43 ppppaul: i have tests all over my test dir, but i haven't used lein test until now and it's failing bad

16:44 bbloom: tgoossens: s/that/what/

16:44 tgoossens: bbloom: ? :p

16:44 bbloom: explain your question please

16:44 tgoossens: ah ok

16:44 hiredman: is there a write up of the core.logic deffact stuff?

16:45 defrel

16:45 tgoossens: bbloom: the dispatch-map dispatches by applying a function to the given inputvalue. In my multimethods i can still use that inputvalue.

16:46 jro_: lein2 run swallows my stdout

16:46 tgoossens: (defmethod command-map ::drive [command] (:blablab command))

16:47 bbloom: oh, no that wouldn't make any sense for dispatch-map b/c the values in a dispatch map aren't necessarily functions

16:47 tgoossens: exactly

16:47 dnolen: hiredman: not really, do you have a specific question? I will say it's still a bit half-baked

16:47 tgoossens: so my "point" was that dispatch map is not really useful for what i'm trying to achieve

16:47 bbloom: (let [value ...] (partial (get (dispatch-map ...) value) value))

16:48 dispatch map is a building block

16:48 tgoossens: also possible is that my current design sucks and i should reconsider it

16:48 bbloom: one thing you can build with it is a multimethod :-P

16:48 tgoossens: :)

16:48 i totally get it now (compared to my comment on your blog :p )

16:49 dnolen: ooh Nashorn source is out, http://blogs.oracle.com/nashorn/entry/open_for_business

16:49 tgoossens: g2g thanks and we speak again!

16:49 bbloom: dnolen: cool

16:51 hiredman: dnolen: no, I just have some code that uses a "database" (a big map) and delves in to the internals of core.logic to provide predicates from the database, and defrel seems like a replacement for that

16:53 dnolen: hiredman: gotcha - you may find defrel pretty yucky. I really made it for myself so I could work through Prolog books. The basic idea is OK but the implementation details need to change, but I'm too busy w/ other things.

16:54 hiredman: dnolen: yeah, I kinda do :) mainly because it is a bunch of calls vs. data as a map, but I can just write something to drive the calls from the map

16:55 francis: Is anyone aware of a clojure tool that removes unused dependancies from namespaces?

16:55 amalloy: $google lein slamhound

16:55 lazybot: [slamhound/lein-slamhound at master · technomancy ... - GitHub] https://github.com/technomancy/slamhound/tree/master/lein-slamhound

16:56 technomancy: francis: disclaimer: doesn't work all that well

16:56 francis: technomancy & amalloy: tried slamhound earlier, didn't work at all

16:56 technomancy: in particular it assumes :require :as aliases are always going to match the last segment of the namespace, and I haven't written code like that since 2011

16:57 however, fixing slamhound would be easier than starting from scartch

16:57 scratch

16:57 francis: technomancy: I'm considering doing that

16:57 technomancy: it's pretty well documented

16:57 francis: It's either that or write my own

16:57 technomancy: http://technomancy.us/148

16:58 francis: groovy, thanks

16:58 ppppaul: i'm looking at how lein's project testing is set up

16:58 i find it a bit strange that there is a lein/test/lein/test/ dir structure...

16:59 technomancy: you mean for leiningen itself?

16:59 ppppaul: yes

16:59 technomancy: that might not be the best example; lein has some weird self-hosting things that make it atypical

16:59 ppppaul: i'm using it as an example of how to set up my project

16:59 technomancy: maybe clojars?

16:59 ppppaul: hmm

17:00 clojars-web / test / clojars / test /

17:00 seems the same

17:01 technomancy: ppppaul: the first test/ dir is there to keep test/ separate from src/

17:01 the second test/ is there because it's part of the namespace name

17:02 ppppaul: i see

17:02 i was able to progress after this realization

17:02 :)

17:09 jro_: I've Emerick et al "Programming Clojure", and just ordered "Joy of Clojure". Could you recommend other books complement those?

17:10 technomancy: those are the best

17:10 ChongLi: Clojure Programming

17:10 technomancy: oh wait, yeah thats' what I meant

17:11 jro_: yes, that is the Emerick's and others book

17:11 I did like it

17:11 ChongLi: Programming Clojure is Halloway and Bedra

17:12 devinus_: Clojure in Action

17:12 is in MEAP isnt it?

17:12 jro_: my weakness now is to design bigger programs using clojure, maybe the language and its abilities are covered pretty well in these two

17:13 technomancy: jro_: a book won't help with that, you need to read code

17:13 ChongLi: I think SICP can help with that

17:14 jro_: yeah, now I just no need to code...

17:15 my first cloure app has so far 46,423 hits :-) and number of active user's are increasing all the time ;-)

17:16 I very pleased about the robustness of the infrastructure: lein, compojure+ring, netty bridge

17:22 dnolen: hmm looks like Nashorn is going to be pretty serious about optimizing JS ...

17:27 bosie: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/if-let it says: "If test is true"... what test is this?

17:28 xeqi: (if-let [.. test] .. ..)

17:30 bosie: xeqi: right

17:30 (if-let [a b]....)

17:30 it would only execute the .... if b is a truthy?

17:31 ucb: bosie: I'd like to think so

17:31 ,(doc if-let)

17:31 clojurebot: "([bindings then] [bindings then else & oldform]); bindings => binding-form test If test is true, evaluates then with binding-form bound to the value of test, if not, yields else"

17:32 bosie: ucb: i read the docs but couldn't make sense of it ;)

17:32 ucb: oh

17:32 xeqi: (if-let [a 5] 1 (throw (Exception.)))

17:32 bosie: ucb: i also dont get what "bindings => binding-form test" means

17:32 xeqi: &(if-let [a 5] 1 (throw (Exception.)))

17:32 lazybot: ⇒ 1

17:32 xeqi: that means you can destructure the test result

17:33 (if-let [{:keys [x y z]} {:x 1 :y 2 :z 3}] [x y z])

17:33 &(if-let [{:keys [x y z]} {:x 1 :y 2 :z 3}] [x y z])

17:33 lazybot: ⇒ [1 2 3]

17:33 bosie: thats interesting xeqi

17:34 thanks

17:45 jballanc_: is anybody doing sql migrations in Clojure?

17:46 technomancy: clojurebot: migrations?

17:46 clojurebot: I don't understand.

17:46 technomancy: clojurebot: migrate.clj?

17:46 clojurebot: unquote in project.clj is an escape hatch

17:46 technomancy: blargh

17:46 jballanc_: here's what I use: https://github.com/heroku/buildkits/blob/master/src/buildkits/db/migrate.clj

17:46 jballanc_: cool, thanks!

17:47 xeqi: for completeness theres https://github.com/budu/lobos and https://github.com/weavejester/ragtime as well

17:47 technomancy: lobos is really complicated though

17:47 xeqi: but clojars uses something like what technomancy linked

17:47 technomancy: and tries to pretend that it's possible to do nontrivial migrations that are portable across databases

17:48 jballanc_: so, let's say someone was interested in adding something akin to DataMapper's automigrations to Korma...

17:48 anyone know the state of Korma development?

17:48 technomancy: I would strongly advise against the development of any system which tries to do migrations in a db-agnostic way

17:48 it's not possible to do well

17:48 jballanc_: heh...understatement of the year

17:49 hmm...ok, I'll think on all these

17:49 thanks for the help!

17:49 dyba: does anyone know how to require a clojure contrib library?

17:49 xeqi: ~contrib

17:49 clojurebot: Monolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

17:49 dyba: I've tried (:require clojure.contrib.math)

17:49 but that doesn't work

17:50 TimMc: technomancy: Naw, man, you just wait until I release my ORM that works across all SQL and NoSQL DBs and also between different runtimes.


17:50 * technomancy waits

17:50 TimMc: We're pushing back our release date just a bit. 2035.

17:50 technomancy: dyba: contrib libraries aren't special; you would load them like any other library after adding them to project.clj

17:50 weavejester: dyba: https://github.com/clojure/math.numeric-tower

17:51 dyba: xeqi: thanks! I'll read up on that

17:51 weavejester: dyba: Add [org.clojure/math.numeric-tower "0.0.2"] to your project.clj deps

17:51 dyba: And then (require '[clojure.math.numeric-tower :as math])

17:52 dyba: thanks technomancy & weavejester!

17:52 I'll give that a try

17:53 technomancy: np

17:59 nDuff: Can agent send operations be forced to block beyond a given queue length?

18:01 llasram: nDuff: I don't believe there's any explicit support for that sort of thing

18:02 Hmm, although -- Agents do expose a public `.getQueueCount` method

18:04 amalloy: one thing i'd like, if anyone feels excited about implementing it, is an agent-like thing where you can specify the queue to use

18:04 technomancy: amalloy: yes please

18:04 err--specifically letting you bring your own thread pool is what I was thinking of

18:04 amalloy: technomancy: i think you can do that in 1.5

18:05 technomancy: no kidding?

18:05 no more shutdown-agents-of-death?

18:06 amalloy: technomancy: (send-via executor agent f & args)

18:06 technomancy: oh

18:06 I guess that's better than nothing

18:06 there's still global defaults hard-wired in that are hands-off

18:06 amalloy: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1895

18:06 no, you can change those too

18:06 technomancy: oh sweet

18:06 llasram: Also `set-agent-send-executor!` if you're into mutating global state

18:07 technomancy: two features I actually care about in a single release! that hasn't happened since 1.1 or 1.2.

18:07 llasram: lol

18:07 reducers are pretty spiffy

18:08 technomancy: I appreciate them in theory but don't see myself using them in practice.

18:11 dnolen: feedback welcome on this one - http://dev.clojure.org/jira/browse/CLJS-448?focusedCommentId=30277#comment-30277

18:11 oops http://dev.clojure.org/jira/browse/CLJS-335

18:30 dyba: by the way I was able to get that contrib library to work with my project

18:31 I will say that I would never have guessed to find the `abs` function in a namespace like clojure.math.numeric-tower

18:32 thanks again to technomancy, weavejester, and xeqi!

18:33 technomancy: there's a Math/abs

18:33 but it doesn't work on all numbers IIRC

18:34 nDuff: Hrm.

18:37 dnolen: bbloom: applying your compiler patches, thanks

18:37 bbloom: dnolen: cool thanks!

18:44 dyba_: ok, so I reached my level of know-how with Clojure after this exception:

18:44 org.apache.lucene.store.LockReleaseFailedException: Cannot forcefully unlock a NativeFSLock which is held by another indexer component: /Users/Paintdexter/.lein/indices/https___clojars.org_repo_/write.lock

18:44 callen: so I converted to using raw ring/clojure, but I'm noticing a lot of repetitious patterns and middleware that 99% of web apps are going to need regardless

18:44 dnolen: bbloom: done!

18:44 dyba_: where would I begin to learn about locking?

18:45 callen: is there some reason Noir is being abandoned when everybody seems to need the same functionality over and over? Would a base template on top of ring make more sense than a framework?

18:45 dyba_: lesson #1: Avoid it unless it's strictly necessary

18:45 dyba_: I feel I might have to read up on promise/deliver since I used that in my code

18:46 callen: so if I'm getting a locking exception, I'm probably doing something wrong?

18:46 callen: dyba_: no I don't know your circumstances, but I'll put it this way

18:46 technomancy: callen: lib-noir isn't being abandoned

18:46 just noir

18:47 callen: technomancy: I'm not sure how much ground lib-noir covers, I'll have to take a look to see if it encompasses the stuff I keep having to do over and over.

18:47 dyba_: locking and threading both get resorted to a lot more than they usually merit.

18:47 weavejester: callen: What sort of things did you keep doing over and over?

18:47 llasram: callen: dyba_ is getting that error I assume just running leiningen, not creating locks him/herself

18:47 callen: dyba_: a good example is when my front-end guy had to implement locks in a frontend JS app and ended up running into deadlocks.

18:48 dyba_: if you're getting a locking exception just from running somebody else's code, I wouldn't sweat it.

18:48 technomancy: dyba_: do you have any concurrent operations going on for this index?

18:48 ibdknox: callen: weavejester: Raynes is going to do a lib-noir template and that should get 98% of the way there

18:49 technomancy: dyba_: sometimes that kind of thing can happen when you mess up when doing interactive development and restarting the process can fix it if it's a simple problem

18:49 weavejester: ibdknox: I was curious as whether it was a templating problem, or something else.

18:49 callen: ibdknox: ah well, we'll see I guess. I can't really wait on other people though. I had an increasingly verbose middleware.clj last night when I was converting to Ring from Noir.

18:49 dyba_: technomancy: I don't think I do

18:49 weavejester: ibdknox: Some good templates would be nice :)

18:49 callen: ibdknox: I could turn the results of what I did into a quick-start Ring template.

18:49 dyba_: I'm not very savvy with concurrent processes. I don't think I'm running anything in parallel

18:49 callen: in fairly short order, I think.

18:50 dyba_: I was working on that fix I volunteered for in Leiningen

18:50 callen: the nice thing about templates is that they're easily fit to purpose.

18:50 ibdknox: weavejester: we've been talking about reworking webnoir into a nice compojure+lib-noir doc site too. Those with templates should get us to a good place :)

18:50 dyba_: and then I decided to use promise/deliver to work with a stream of bytes I get when I run the search command

18:51 then for the input stream i use an atom to track the number of bytes read

18:51 I can provide a link to the code if anyone is interested in looking into it

18:51 technomancy: dyba_: sure

18:51 callen: dyba_: why are you using promise?

18:51 dyba_: https://github.com/dyba/leiningen/blob/master/src/leiningen/search.clj

18:52 callen: I have no idea what I'm doing :/

18:52 callen: dyba_: that's me every single day, just ask any of the others here. :P

18:52 dyba_: phew, I just keep telling everyone I'm a newbie

18:53 technomancy: dyba_: I think promise is appropriate here if you're just trying to capture proxied .setFoo args

18:53 dyba_: have you tried just deleting the index in question and trying again?

18:53 dyba_: technomancy: how would I do that? you mean rm -rf .m2 ?

18:54 technomancy: dyba_: no, ~/.lein/indices rather

18:54 dyba_: oh let me try that

18:54 bbloom: dnolen: awesome! one more while you're at it :-) http://dev.clojure.org/jira/browse/CLJS-424

18:55 callen: one concern I have about publishing a template is that my base I'm using to fix up all my apps use hiccup.

18:55 for the error pages et al

18:56 I was hoping to avoid being overly opinionated to that end.

18:56 dyba_: technomancy: hm, same problem

18:57 maybe if I get rid of that atom inside the input-stream-proxy function

18:57 ha, just realized I didn't share the right branch

18:57 https://github.com/dyba/leiningen/tree/progress-reporting-search-index

18:57 ugh

18:57 wrong file

18:58 https://github.com/dyba/leiningen/blob/progress-reporting-search-index/src/leiningen/search.clj

18:58 technomancy: dyba_: the lock error just means that multiple writers are trying to be opened on the same index

19:07 alex_baranosky: technomancy: any suggestions when looking at slam hound with an eye towards fixing it up? Francis and I might try to work on it over the next week and get it working so we can use it on our work projects

19:08 dnolen: bbloom: will have to look at that later, I see have a backlog since I've been working on core.logic so much

19:09 bbloom: is this still relevant? http://dev.clojure.org/jira/browse/CLJS-412

19:11 bbloom: dnolen: let me think about CLJS-412 for a second

19:11 technomancy: alex_baranosky: that'd be tops. let me take a peek.

19:12 dnolen: bbloom: well I responded, I might jet so soon so leave a comment :)

19:12 bbloom: dnolen: i think the first comment was a typo

19:12 shoulda been defn

19:12 dnolen: bbloom: yep I put that in, no warnings

19:13 technomancy: alex_baranosky: the primary problem right now is that the heuristic for replacing :require :as is rubbish; you'd need to accumulate over a list of all attempted aliased references as they come up and when there's a new failure pick a namespace where all the aliased vars still appear

19:13 alex_baranosky: does that make sense? happy to answer questions as they come up if I'm around

19:13 bbloom: dnolen: did you have warn on undelcared enabled?

19:14 technomancy: alex_baranosky: also you'll want to replace :use with :require :refer

19:14 but I don't think that'd be difficult

19:14 dnolen: bbloom: that's the default for Rhino REPL

19:15 technomancy: alex_baranosky: I'm not sure how difficult it'd be to keep a running list of failures; that's probably going to be the primary challenge. but the existing codebase is pretty tiny and fairly well-factored

19:16 wish I had time to hack on it; that's a really fun codebase

19:16 bbloom: dnolen: hmm dunno about that first comment, but i def get the issue from the original body

19:17 dnolen: https://gist.github.com/4356706

19:19 dnolen: bbloom: yes but does that happen at the REPL or in a source file?

19:19 bbloom: in anycase I have to go - I need a lot more information about what you are trying to do.

19:19 bbloom: dnolen: it happens when i use analyze

19:19 but no not in the repl any more it seems

19:19 dnolen: bbloom: so an explanation of why not in the REPL & yet at analyze would be helpful.

19:19 gotta run

19:20 bbloom: dnolen: cya

19:23 alex_baranosky: technomancy: sorry, got distorted… yes that makes sense. I was thinking as enhancements it'd be nice to configure whether you want :use/only or require/refer… require/refer doesn't work on 1.3 right?

19:23 but first thing is to make it work :)

19:23 technomancy: I've got to run, but will keep you posted

19:27 technomancy: alex_baranosky: I wouldn't bother with 1.3 support

19:27 1.3 is best forgotten

19:27 plumbing configurability all the way through for such a minor feature isn't worth the complexity

19:51 bbloom: why do academics insist on fancy typography, even when they are showing source code for a language that is *usually* written in ascii? We get it, you think \Lambda looks nice. But some of us are trying to read your paper....

19:53 callen: bbloom: the poltergeist of APL haunting us

19:53 bbloom: also: LaTeX

19:55 bbloom: i can maaaaaaaaaaybe understand space requirements in journals, etc, but for an unbounded digital dissertation, what motivation could there possibly be for inventing your own syntax for scheme? it's gotta be a cargo cult situtation...

20:04 llasram: bbloom: Are you reading the FrTime paper?

20:11 yedi: https://github.com/doo/process

20:11 pretty sweet

20:13 paultag: Anyone know how to get unbuffered stdin in Clojure? I'm a bit new, it'd help a lot if you had a small example (but doc pointers would be great too)

20:14 cemerick: paultag: that might require going straight for System/in

20:15 Raynes: If I need unbuffered in and out, I go straight for System/*

20:15 paultag: righto. thanks

20:15 Raynes: I couldn't get it unbuffered from *out*, so I expect the same would make sense in *in*.

20:15 paultag: what, that it's buffered still?

20:15 seangrove: What's GClosure? This https://github.com/rhysbrettbowen/G-closure ?

20:15 paultag: Ah, right.

20:15 Yeah, sorry took a seec

20:16 sec* thanks, y'all.

20:16 seangrove: dnolen recommended people use it to pass objects from potentially different contexts

20:18 paultag: is there something like `progn' in Clojure?

20:18 ah, do. right, nvmd.

20:20 scottj: seangrove: GClosure is Google Closure

20:21 seangrove: Ah. Wonder how that's related to passing object between contexts

20:21 Raynes: Telling someone GClosure can do what they want is like telling someone who is hungry that a grocery store can do what they want.

21:10 callen: Raynes: GClosure isn't really useful unless you have a lot of really big frontend apps that you want to be able to reuse code across.

21:11 a lot of their adops people are trying to push angular to replace a lot of the ajaxy functionality.

21:17 seangrove: callen: The ui widgets seem very nice, the event bus stuff is reasonably nice, the DOM stuff is solid if ugly (though things like domina make it nicer), the promise/deferred stuff isn't too bad... the ajax stuff is *meh*, but I haven't used it much yet

21:17 Curious what you mean by it not being super useful

21:17 Also really curious about people pushing for angular to replace the ajax parts and why that'd happen

21:25 callen: seangrove: the UI widgets aren't useful for most customer-facing development.

21:26 seangrove: angular is a more declarative and data-driven approach to frontend dev, it's being used all over Google but the strongest proponents are the people in their ad depts. The devs who work on Angular that I know are mostly in NY.

21:26 seangrove: Angular is pretty nice, I think Goodreads did a write-up on building a mobile web app in Angular.

21:27 Angular does a lot to prevent event/data spaghetti on the frontend, but is more generally applicable to a variety of problems than Backbone.

21:28 weavejester: so is most of your contracting work Clojure work then?

21:28 weavejester: callen: All of it so far

21:30 callen: weavejester: that's pretty great. Most of what I heard about Clojure so far mostly concerned using it as a secret weapon in Enterprise Java environments.

21:30 Supposedly this is partly what spurred Hickey on, beyond his ongoing language experimentation.

21:31 weavejester: is it mostly backend, full-stack, new stuff or building on existing stuff?

21:31 weavejester: There's a few businesses in London starting using it. Forward and Likely spring to mind.

21:31 callen: I've currently just had two contracts - I only started back in July :)

21:32 callen: One was for a web service that was semi-client facing.

21:32 callen: weavejester: cool, thanks for sharing. It seemed like the Clojure work was bimodal, either it was being snuck into a Java environment or a startup was using it from 0

21:33 weavejester: watching your talk on clojure web dev. Thanks for your work on Ring!

21:33 weavejester: callen: Another deals with big data - cascalog, hadoop, that kinda thing

21:34 callen: You're welcome

21:34 Now….

21:34 I gotta get to bed :)

21:34 callen: Cheers :)

21:45 ferd: can somebody point me to "substantial" open-source apps built in Clojure?

21:46 callen: ferd: gimme a specialization broskie

21:46 ferd: I can help you but you need to tell me what you want to see.

21:46 ferd: e.g. Web app, big data application, etc.

21:46 data store library...

21:47 ferd: a web app would work

21:47 I'm looking for complete business apps (not specialized libraries) ... I want to draw ideas around how to structure non-trivial codebases

21:47 callen: https://github.com/Raynes/refheap go with my classic stand-by for checking for idiomatic patterns in Clojure web apps then.

21:47 ferd: I'm actually cobbling together a template for Clojure Ring apps atm because I'm migrating away from Noir. I'd look at RefHeap for now though, Raynes is 300x more experienced at Clojure than I am.

21:48 I used to use Noir + Stencil, I'm switching to Ring + Hiccup.

21:50 ferd: Thanks

21:50 callen: ferd: np. let me know if you have any questions. My work tends to be along the lines you described.

21:50 ferd: business and consumer facing web apps.

21:52 ferd: for now I'm looking for good practices for structuring namespaces, managing configuration, environments, abstracting data-access layer (I might need to support a couple of options), mapping (say, from client's JSON to a diff. structure for persistence)

21:53 callen: ferd: well, you're basically asking to become professionally competent in the entire language. Refheap is a good reference for reminding yourself of idioms but the best way to learn and *internalize* those things is to just start hacking on a side project until it sticks

21:53 which has been my way of learning Clojure. It's worked well for me, better than books.

21:53 although I've been fond of a few.

21:54 ferd: I just solved that configuration/environment problem last night. I'm not 100% satisfied with it but I'm confident it's fine for now.

21:56 arohner: your cofounder was suprisingly gracious about a relatively petty spelling-fix pull request.

21:57 arohner: you wouldn't happen to be able to comment on how you guys use Dieter, would you

21:57 pretend there was a question mark at the end of that.

22:14 technomancy: ferd: clojars is the most widely-used OSS clojure web app

22:15 it's been around a while but I think for the most part exhibits good design

22:16 ferd: thanks... taking a look at it now...

22:21 sgeo_: ,(resolve 'first)

22:21 clojurebot: #'clojure.core/first

22:21 callen: ferd: clojars is even bigger than refheap, technomancy makes a great suggestion.

22:22 ferd: yeap... excellent

22:22 technomancy: as long as you ignore the fact that it uses sqlite

22:22 =)

22:22 ferd: :-)

22:22 callen: technomancy: I cringed.

22:22 ferd: I plan on using Mongo or Datomic

22:22 technomancy: callen: it was fine until we started to add background tasks

22:22 callen: ferd: do you have some reason for doing so?

22:23 technomancy: oh yes, multiple writers to a single sqlite database.

22:23 technomancy: always a great idea.

22:23 technomancy: callen: I originally thought that it was just multiple processes hitting the same DB that wouldn't work

22:24 nope! it's threads. *facepalm*

22:24 callen: I generally use sqlite when I need to stash something in something vaguely approximating "a file", but I want indexed access to rows. Anything beyond that...meh. Use a real database, failing that, use Redis if you want something lightweight.

22:24 technomancy: well it's anything that means "multiple writers"

22:24 technomancy: doesn't matter if it's threads, processes, whatever.

22:25 technomancy: the docs say multiple processes but in the fine print there's "if you're in a multi-threaded runtime, substitute threads for processes as you read this"

22:25 callen: that's why I specifically use the wording multiple writers so that people don't mistake implementation for semantics.

22:25 xeqi: as soon as I replace search I can see about changing the db

22:25 ferd: callen: yes... the app I need is very "document"-oriented

22:26 callen: ferd: well lets talk about that. I have a lot of experience with MongoDB and as a result spend a decent amount of time warning people off it.

22:26 technomancy: xeqi: you are a hero =)

22:26 callen: ferd: what do you mean by document oriented in this case? it's fairly application specific.

22:26 xeqi: we love you. (use postgres)

22:26 xeqi: how are you doing search perchance? that happens to be a knack of mine.

22:27 technomancy: xeqi: I hope to get an email out this weekend explaining the situation around promotion

22:27 then maybe a preview11 after christmas

22:27 xeqi: callen: still trying to decide, could just use lucene on the premade repo indexes

22:28 ferd: well... I mean, I have entities which are basically a lot of hierarchical data fields... and each "instance" will vary on which pieces of data it has or not

22:28 callen: xeqi: could do that. I'd avoid using Lucene in the raw unless you have a specific reason for doing so though.

22:28 xeqi: but I don't see an easy way to score based on downloads with that

22:28 callen: xeqi: I understand there are some uncommonly good lucene libraries for clojure, but it's kinda rough for most use-cases.

22:28 ferd: so, definitely more natural to think of them as hierarchical "documents" than SQL tables

22:28 callen: xeqi: have you considered ElasticSearch?

22:28 technomancy: elasticsearch makes no sense for a corpus this size

22:29 callen: I regard ES as being fairly lightweight and easy to use as contrasted with using raw lucene indices.

22:29 technomancy: I mean, unless you're going to expose a rest API to 3rd party tools or something

22:29 callen: our non-programming data guy figured out how to set it up himself.

22:29 xeqi: I've only started digging into it today, os still in the exploration phase

22:30 technomancy: there's no need for dynamo-style clustering for a 5MB index

22:30 xeqi: never had to plug in fts myself yet

22:30 callen: technomancy: it's not about the clustering, it's about the high-level featues.

22:30 technomancy: ES has a lot of nice high-level features for things like scoring.

22:30 and dynamic sorting

22:30 seangrove: Why do we love xeqi?

22:31 callen: technomancy: I'm not utterly incapable of applying reason, I know he doesn't need anything "webscale" so to speak. I recommended it because ES solves a lot of really common problems you run into if you're using lucene on its own.

22:31 seangrove: technomancy: and what does "promotion" mean in this context?

22:31 technomancy: I dunno; raw lucene was really pleasant for me to use when I wrote lein search

22:31 xeqi: seangrove: cause I spend freetime on clojars

22:31 ferd: callen: so, what are your main points against MongoDB ?

22:31 seangrove: Ah, thank you xeqi, you're awesome ;)

22:32 callen: ferd: sorry, hold on :P

22:32 technomancy: seangrove: clojars has a separate "releases" repo that only accepts packages that qualify around certain metadata criteria

22:32 callen: technomancy: clojars is a web app that's going to have concurrent clients, not a local-only command line service

22:32 technomancy: seangrove: so packages need to get promoted from the "classic" repo into "releases"

22:32 callen: technomancy: the needs are different and he wants to have intelligent human-facing scoring

22:32 seangrove: xeqi: Is there an open list of bugs/features others can work on?

22:32 callen: to use raw lucene here is the same sort of mistake as using sqlite for a public-facing webapp to begin with

22:33 technomancy: lucene works fine for concurrent reads

22:33 seangrove: I wouldn't mind taking a look at it sometime, maybe for a hackathon or something

22:33 callen: technomancy: step away from the specifics for a moment

22:33 technomancy: the indices are already generated asynchronously, so concurrency is a non-issue

22:33 callen: technomancy: how is going to efficiently do custom scoring with raw lucene?

22:33 technomancy: he'll end up duplicating the effort Baron already put into ES

22:33 technomancy: callen: in the case of clojars, the indices already exist; they are published for Leiningen

22:33 xeqi: seangrove: https://github.com/ato/clojars-web/issues , but there needs some classification for easier tasks

22:34 seangrove: Yeah, was just looking through that, seems like some pretty specific stuff

22:34 callen: technomancy: if it's a case of reusing existing code and functionality, so be it

22:34 technomancy: but more advanced user-facing features are going to be painful.

22:34 technomancy: xeqi: are you getting download counts from the nginx logs?

22:35 need to enable logs on the S3 bucket too; hmm.

22:36 xeqi: technomancy: think _ato had some work that direction

22:36 callen: technomancy: the fact that lein is already using them and that has some sort of symmetry with clojars is the real winning argument in favor of raw lucene btw.

22:36 technomancy: cool

22:36 callen: ferd: right, okay.

22:36 xeqi: was hoping to be able to plug that in to make search rankings better

22:36 automatic canonical finding, etc

22:36 callen: ferd: usually you just want to use a SQL database, commonly Postgres unless you have a good reason to the contrary.

22:36 technomancy: callen: can you run ES entirely in-process?

22:37 callen: one of the great things about clojars right now is that you can hack on it without any external dependencies; everything's in the JVM

22:37 callen: technomancy: yes, it's a thing that's done.

22:37 technomancy: it's not an officially supported use-case, but that's definitely a thing.

22:37 technomancy: ok cool; when we were using it that was really hard to set up

22:37 but that was a long time ago

22:37 callen: technomancy: at heroku or with clojars/lein?

22:37 technomancy: at my last job; http://sonian.com

22:38 callen: technomancy: odd. as I said a guy who only just learned to code was able to set it up himself and he was barely able to handle his python dependencies in the past.

22:38 technomancy: besides that, we've got some fairly involved multi-cluster deployments

22:38 you...don't want to know what cross-cluster data migration is like with ES. It's worse with Solr.

22:38 it resembles Riak, actually.

22:38 technomancy: sure; it's not difficult to set up a separate server along side clojars while developing, but it's tedious

22:39 callen: calling it dynamo like really doesn't do it enough justice. It does a better job at rebalancing than other dynamo-likes like Cassandra.

22:39 ferd: callen: well... my entities will contain 30+ fields each... and each "record" will only fill about 20 of them depending the kind. If I model that in SQL, it'd be ~5 diff. tables to store a single entity

22:39 technomancy: little impediments like that are actually more appropriate in a work environment than an OSS project, because people are more likely to get bored and move on =)

22:39 callen: I agree it's very impressive at large scale.

22:40 callen: ferd: what I understand so far, it's not a great reason just yet to use MongoDB

22:40 technomancy: just a bit skeptical that it scales in the other direction =)

22:40 callen: ferd: try to understand that the schema-free nature of MongoDB is seemingly convenient but that means it demands more, not less thought be given to data modelling.

22:40 technomancy: I would be too. it's memory-hungry.

22:40 ferd: callen: so, I was under the impression that mapping the conceptual "document" from higher layers (say, JSON from the UI) would be easier in Mongo than SQL

22:41 callen: technomancy: it's very aggressive about keeping things in-memory to satisfy soft realtime constraints.

22:41 ferd: callen: is there any good reading (book, or deep articles) to help me ?

22:41 xeqi: callen: thanks for the pointers, had someone else mention ES before, I'll have to take a look at it

22:41 callen: ferd: it resembles JSON, but migrations, schema changes, and general modelling are harder not easier to do correctly in MongoDB.

22:41 ferd: you should get a book on data modelling in SQL, learn to do it right there

22:41 ferd: once you learn the right way to do it there, you'll be better prepared to make a decision between a SQL DB and MongoDB

22:42 ferd: honestly, I like what I see on Datomic better... it's just that it's not very popular nor open source ... and I don't yet know how much the "free" edition can stand

22:42 callen: ferd: if you don't already have very strong opinions and lots of experience with data modelling MongoDB is *not* the way to go

22:42 ferd: callen: I've been using sql for 15+ years... not an expert, but... no need to read more for now :-)

22:42 callen: if I hadn't had a lot of experience contracting in feature-creep heavy enterprise projects I would've been boned when we used MongoDB

22:43 ferd: then I don't know what to tell you. If you posted some potential JSON representations of the data you're thinking of, I could start working in the conrete

22:43 concrete*

22:43 technomancy: I would take couch over mongo any day.

22:43 seangrove: ferd: wei_ and I hacked on a side-project to get to know datomic, and the free version can hold up well, *but* it's an entirely different experience than with postgres et al

22:43 callen: xeqi: sure but from what technomancy is saying, it seems like most of the clojars developers want a complete embedded and in-process deployment story.

22:43 technomancy: I would not @ couch.

22:44 technomancy: couch is insanely irritating and slow.

22:44 clojurebot: Ok.

22:44 seangrove: technomancy: I would shoot couch any day

22:44 technomancy: callen: mostly because it doesn't set unrealistic expectations

22:44 seangrove: Second to mongo, no software has ever caused me to wake up more in the middle of the night than couch

22:44 callen: technomancy: CouchDB is a data roach motel

22:44 "data goes in, but never comes back out"

22:44 ferd: I see couch, indeed, another alternative.... I though of Mongo just 'cause it seemed more popular and better supported

22:45 callen: couch is best for non-user-facing data archival and roll-ups

22:45 technomancy: ferd: are you sure it's not just "people blog about it more"?

22:45 seangrove: Couch could be alright, but in general everything seems wrong about it

22:45 technomancy: Our post about CouchDB http://sauceio.com/index.php/2012/05/goodbye-couchdb/

22:45 Ot

22:45 technomancy: yeah actually couch's strengths like on the client side with putting the user literally in control of their own data

22:46 seangrove: It is - generally - very cordial given team sentiments

22:46 ferd: wondering if I'll find a DB that nobody will bitch about here :-)

22:46 technomancy: but I'd still take it over mongo =)

22:46 ferd: postgres

22:46 callen: the three most common databases among founders that I encounter are MySQL, PostgreSQL, and MongoDB.

22:46 seangrove: ferd: postgres

22:46 Especially on Heroku

22:46 callen: ferd: postgres

22:47 ferd: OK... I'm very familiar with postgres... so that's good

22:47 callen: postgres is blameless. It lives up to its mission and it's fine for 99% of projects.

22:47 it's not flawless, it just does what it says.

22:47 seangrove: callen: I'd add more nines to that

22:47 callen: seangrove: I wouldn't, I work at a company that uses and needs MongoDB and ElasticSearch :P

22:48 seangrove: But yes, if you've outgrown postgres, then you've done an awesome job and are a good engineer, most likely

22:48 callen: takes less than you think

22:48 technomancy: seangrove: if you've outgrown postgres, you're probably not looking for DB advice on IRC =)

22:48 ferd: I was hoping to avoid tons of mappings from JSON to SQL entity-roots and an explostion of sub-entity tables

22:48 callen: highly sparse data schemas are pretty rough in tabular row-stores.

22:48 seangrove: technomancy: True, true

22:49 I got an email from you guys accusing me of using env vars on Heroku as a database ;)

22:49 callen: incidentally I consider persistence and search to be my favorite subjects and they also happen to be the subjects I seek the least amount of advice for on IRC

22:49 seangrove: The last line was, "Have you ever heard of Heroku Postgres?"

22:49 technomancy: seangrove: haha; nice

22:49 callen: seangrove: 12-factor?

22:49 seangrove: I still can't figure out if it's a sarcastic line or not

22:49 technomancy: seangrove: pretty sure it is

22:50 callen: 12-factor deployments can often be mistaken for ENV var as a data-store.

22:50 seangrove: callen: Yeah, more or less

22:50 callen: I'm psychic.

22:50 seangrove: It was required as a shim for deploying to our own PaaS, dotCloud, Cloud Foundry, and Heroku, in order to do it seamlessly

22:50 callen: I consciously chose not to do 12-factor.

22:50 technomancy: seangrove: an object lesson in the importance of adding caps sooner rather than later =)

22:51 seangrove: technomancy: I suppose

22:51 It wasn't abusive

22:51 technomancy: seangrove: for us, I mean

22:51 seangrove: And it was within the limits supported by linux's env, etc.

22:51 Oh, yes, I know

22:51 You guys are generally very good at that

22:51 By the way, you're not out here in SF are you?

22:51 callen: technomancy: 12-factor apps can end up having hundreds of env vars. It's pretty typical for projects that are hyper aggressive about deployments.

22:51 technomancy: seangrove: sure, but we are changing the backing store and found that some (very small) number of configs wouldn't work in the new one

22:51 callen: well, dev-ops, lets say.

22:51 technomancy: seangrove: nah; seattle

22:52 callen: I'm in MV.

22:52 seangrove: technomancy: Bummer, you guys have a great team out here

22:52 technomancy: callen: haven't seen it myself, but I have only deployed small apps on the platform

22:52 seangrove: I visit every couple months, which is about the right amount of SF for me =)

22:52 seangrove: I've heard that clojure is more or less out of Heroku these days though, sadly

22:52 Something about it being too hard to hire for

22:52 ferd: anybody has an opinion on Datomic? I really like the model, but not sure if I can trust the free edition... (I don't need Dynamo-level scalability, not even close)

22:53 seangrove: ... and yet you persist in using Erlang ;)

22:53 technomancy: seangrove: there was only ever one clojure app in use internally

22:53 seangrove: ferd: If it's for a production-level app, don't use Datomic

22:53 technomancy: though I might be introducing another; we'll see

22:53 seangrove: That must be some kind of universal law

22:53 "Never use a database you don't have personal experience with as the foundation of your new production-grade business app"

22:54 Always screw around with it first

22:54 technomancy: the project I spend most of my time on just isn't a good fit. since mcgranaghan switched to Go I don't think there are any other clojure fans at work.

22:54 callen: technomancy: did he make a post about why he switched?

22:54 technomancy: seangrove: there's no replacement for Erlang for what we're using it for

22:54 callen: as far as clojure hiring, I've always seen it as something you don't hire directly for.

22:54 technomancy: callen: no, but I know that he never used a repl when writing clojure

22:54 seangrove: Yeah, that was the turning point from what I heard, when even Mcgranaghan gave up

22:54 callen: Rather, somebody volunteers to teach the next hire that is interested in it.

22:54 technomancy: so it's no surprise he didn't mind writing Go

22:54 callen: and that scales up in a double-fashion quickly.

22:54 technomancy: ...never used...a repl?

22:55 technomancy: callen: a victim of Textmate

22:55 callen: poor bastard.

22:55 seangrove: ouch

22:55 technomancy: maintaining his stuff was all "OK, you made a change; now deploy it to staging to see if it works"

22:55 insane

22:55 callen: technomancy: I actually shied away from Go because the entire community told me I didn't need a debugger or a REPL.

22:55 technomancy: not exaggerating.

22:55 seangrove: technomancy: Yeah, Erlang comment was tongue-in-cheek

22:55 technomancy: callen: yep. completely baffling.

22:55 there's no excuse for ignoring interactive development. life is too short.

22:55 callen: technomancy: why did testing his code require abusing staging? no unit tests?

22:56 technomancy: callen: yeah that too

22:56 callen: technomancy: their counter-argument was that type signatures and documentation should be enough @ interactive development.

22:56 technomancy: so it's actually kind of relieving that app has been retired

22:56 haha

22:56 type signatures; the ones that are required because you have a crappy inference engine?

22:56 * technomancy golf claps

22:56 callen: LOL

22:57 I really have to think that the sort of people who think they can do without interactive development haven't done any seriously complicated development that meant interacting with unfamiliar code or libraries

22:57 spend their whole lives in the stdlib.

22:57 my contracting work was too vertical to be like that.

22:58 incidentally Go's equivalent to ring is actually part of the stdlibs.

22:58 seangrove: go does allow for some pretty impressive code:functionality ratios, and stays readable

22:59 callen: seangrove: I *like* Go, that's why I said I shied away from after having to confront the rest of the community

22:59 seangrove: they just lack taste.

22:59 seangrove: Heh, they're alright

22:59 technomancy: yeah and gofix is an amazing feat for a non-homoiconic language

22:59 seangrove: At least when comparing them to the CL community

23:00 And yes, gofix is awesome

23:00 technomancy: but you have to draw a line somewhere

23:00 and for me it's that I won't go back to punch cards

23:00 seangrove: Hrm, I wonder if community is the right word in CL's case...

23:00 Warzone maybe?

23:00 callen: seangrove: dude. CL was my original serious PL

23:01 technomancy: I tried it with Mirah (where I had the excuse of wanting to target mobile) and said never again.

23:01 callen: seangrove: C# and Python, which came after CL for me, were like dying and going to heaven.

23:01 seangrove: Heh, I love CL in many ways, it's mind-blowingly cool

23:01 But it's impossible to get any consensus in the community, and everyone is extremely hostile

23:01 callen: seangrove: I was trying to get work done. To that end, CL was painful in many non-trivial ways.

23:02 n_b: I went Java->Python->Ruby->JS->Clojure in learning order, every one has been a step up except for JS

23:02 callen: seangrove: in the end, using CL means doing everything yourself. Absolutely no division of labor or real community-wise code reuse beyond things like WHO and Hunch.

23:02 seangrove: callen: CL's fine for getting work done, particularly with quicklisp these days

23:02 n_b: Clojure has the friendliest community, Python the broadest range of application+well-written code, Ruby the largest # of mono-lingual devs

23:02 seangrove: But yeah, its' difficult

23:03 n_b: I wanted to pick up CL or an ML next, but the communtiy aspect makes it daunting

23:03 technomancy: n_b: erhm; ruby more than Java even?

23:03 callen: seangrove: quicklisp makes it easy to get libraries you can't use to begin with :P

23:03 seangrove: n_b: Interesting's point about ruby mono-lingual devs...

23:03 n_b: technomancy: Yes, but that's a view shaped by only doing Java @ Google

23:03 callen: seangrove: try using a CL library written by a guy who read Let over Lambda, let me know how that goes for you.

23:03 seangrove: callen: And lots of them!

23:03 clojurebot: callen: there's a small subset of things you *can* do in paredit that I actually do -- I would imagine the same is true for most

23:03 technomancy: n_b: ah, that makes sense

23:03 seangrove: callen: I've written tons of them ;)

23:03 technomancy: callen: hah

23:03 seangrove: So I'm part of the problem, hah

23:03 callen: seangrove: see? this is why I'm here.

23:04 seangrove: LoL is amazing though... definitely enjoyed it

23:04 Abused the hell out of it

23:04 callen: restraint and taste are very important to me. That's why I went Python after using Python and Ruby at the same time for a few years.

23:04 seangrove: And I'm all better now... mostly

23:04 n_b: and I'll never even go so far as to suggest I'm a competent Java dev, so I can't speak to it much. The perspective I have on it is very unusual

23:04 seangrove: callen: Clojure's definitely in a nice spot for that so far

23:04 callen: seangrove: agreed.

23:04 n_b: callen: Ruby taught me a great deal about metaprogramming and made me a much better Python developer; frankly I don't enjoy using either nowadays

23:05 callen: restaint, taste, and power all in one package.

23:05 seangrove: But isn't Haskell more so?

23:05 callen: n_b: python is still my day job, I don't mind it, but OTOH, the codebase is my personal kingdom of functional programming.

23:05 seangrove: I've been increasingly impressed with some of the ideas behind Haskell these days

23:05 callen: seangrove: Haskell is BDSM incarnate.

23:05 n_b: FP in python is ehhhh

23:05 callen: Haskell was a great learning experience, but I'll never use it for anything I care about.

23:05 seangrove: Why's that?

23:05 n_b: seangrove: the restraint and academic background crimp its power in a number of places

23:05 callen: Haskell did a lot to improve my Python code.

23:06 seangrove: n_b: I'm not sure...

23:06 n_b: the default string impl, for one, is a linked list

23:06 seangrove: I think it may end up fulfilling the goals of Lisp in a more powerful way

23:06 callen: n_b: there a lot of reasons not to use Haskell, that's not precisely one of them.

23:06 n_b: more importantly, there are 3 or 4 prominent string types that all work differently and seem to have half-overlapped use-cases

23:06 for which any given 3rd party library can choose to use any mix of them they like

23:06 n_b: I'm aware, it's just one of the things that immediately springs to mind

23:06 callen: which means you end up doing a ton of typecasting all over your damn code

23:06 *irritating*

23:07 also cabal is a Lovecraft Horror of the first order.

23:07 n_b: my knowledge of Haskell is informed entirely by my roommate having taught it to me, and then going through The Haskell Road. Can't comment to using it productively and would defer to others.

23:07 callen: cabal did a LOT to make me stop using Haskell.

23:07 n_b: Cabal2 is better! _we swear_

23:08 callen: whenever a buddy that uses haskell asks me why I went 100% clojure for side projects, I usually point to leiningen and compare it with cabal.

23:09 n_b: Where's that quote about the #haskell community and it's tendency to immediately jump to arguments about the most generic way of doing something?

23:09 TimMc: callen: When you say that Clojure is not usually something one "hires for", do you mean that you don't restrict yourself to hiring existing Clojure users?

23:09 seangrove: callen: You've certainly got a lot of reasons why you've stopped using languages ;)

23:09 callen: TimMc: yes, and it puzzles me when people claim you have to do so.

23:09 TimMc: Me too.

23:09 callen: Clojure is not difficult to learn and a lot of backgrounds are good for learning it.

23:09 Python, Ruby, and Java people are all well suited to learning it, if they want to learn FP.

23:10 TimMc: That's one of my pet peeves: People overestimate the difficulty of learning languages and underestimate the difficulty of learning tools, libraries, and services.

23:10 callen: the O'Reilly book is well designed.

23:10 TimMc: THANK YOU! Yes. That.

23:10 TimMc: I think it's because they usually only know one of the former and many of the latter.

23:10 callen: TimMc: that's why leiningen is so important to me.

23:10 TimMc: tools can turn into a bigger time-suck than your problem you're solving in a hury.

23:10 TimMc: Because it's dead easy?

23:10 callen: hurry*

23:10 TimMc: and well-designed, etc etc

23:11 TimMc: "Oh, you know Java? Good. Now let's get you up to speed on our 35 tera-LOC codebase."

23:11 callen: TimMc: incidentally I know a Java dev that is terrified of and refuses to use any other languages

23:11 TimMc: I figured out why...he didn't really understand what he was doing

23:12 he only understood IntelliJ and Spring

23:12 and anything outside Spring and IntelliJ, he didn't understand a whit.

23:12 Like say, basic unix principles. 0 comprehension.

23:12 n_b: I don't understand how that happens

23:12 I can understand knowing something else and not understanding Java

23:12 callen: n_b: I don't either, but this character is starting to build a picture for me as to how it happens

23:12 n_b: It took me a couple of books and tons of time in a code base to figure out the typical design patterns

23:12 callen: it seems to largely arise from complaceny and over-reliance on familiar tools.

23:13 TimMc: callen: Tab-complete your way to working software!

23:13 callen: TimMc: yeah that's actually how he codes.

23:13 TimMc: it took ages to explain to him why I use Emacs.

23:13 TimMc: It's how *I* code.

23:13 I mean, at work, when doing Java.

23:13 callen: TimMc: there's nothing wrong with it as long as you understand what's going on

23:13 the problem is, the "helpers" were a crutch for him

23:14 renderful: they refer to these people as brogrammers

23:14 seangrove: n_b: Linux is a rabbit hole of knowledge

23:14 callen: renderful: kinda-sorta. Brogrammers is more of Ruby/Rails community archetype.

23:14 seangrove: It's not something you "just pickup" unless you're really banging away at it

23:14 renderful: callen: yes, because they rely too much on Rails magic

23:14 TimMc: I'm largely working with existing libraries, so it's not unreasonable.

23:14 renderful: which is similar

23:14 callen: seangrove: I learned Linux by using over 100 different distributions and just constantly breaking and reconfiguring shit.

23:14 took years. pretty big timesink.

23:14 renderful: same for me callen

23:15 15 years so far

23:15 seangrove: But that's my point

23:15 callen: if I didn't do a fair bit of dev-ops alongside my coding these days, it'd have been a pretty big waste.

23:15 seangrove: I've use it for years

23:15 callen: renderful: similar number of years here, I started with Red Hat 5

23:15 seangrove: Wasn't until I had to build something paas-like out of it, and later lxc, that I started to grok some of the ideas and implementations behind it

23:15 renderful: yar, slackware 3 i believe

23:15 TimMc: I picked up GNU/Linux in 2005. I now feel confident in using dd without wiping my hard drive. It's been... an interesting journey.

23:16 callen: I started from a young age, so some of my time was misspent

23:16 seangrove: Point being, that I would in no way expect someone who says they "know Java" to "know linux"

23:16 callen: but I started with Linux in 1998

23:16 seangrove: Heh, the glory days of wasted time

23:16 renderful: most of my time was misspent :)

23:16 TimMc: seangrove: Wait, where did Linux come into this? I think I missed something.

23:17 callen: seangrove: I guess, but my point is that he was unwilling to learn and was afraid of anything outside of his cocoon.

23:17 renderful: but i love all of that time that i spent doing bullshit and making mistakes

23:17 seangrove: callen: Ah, yes

23:17 callen: TimMc: what I said about the dude being clueless outside of generating java and XML in his IDE

23:17 ioexception: Using windows for Java dev, is a bit painful to me, no tools.. no grep, no less, no shell...

23:17 TimMc: Oh, I see it now.

23:17 n_b: seangrove: The way I took "didn't understand what he was doing" was that as a programmer he lacked a mental model and was cargo culting via intellisense to software; I would absolutely not expect someone to go from JVM->kernel dev

23:17 callen: seangrove: you should at least know some basic unix commands if you're deploying to Linux servers on a regular basis.

23:17 what n_b said.

23:17 n_b: I'd expect someone to go from using Play! to Rails without issue

23:17 seangrove: It's important to have an attitude of "Fuck, another problem? Alright, have to solve it. A kernel compilation problem? Alright... let's look that up..."

23:18 callen: n_b: agreed although Rails has a pretty deep rabbit-hole of conventions.

23:18 ioexception: n_b: high expectations, not the common human

23:18 TimMc: You can get surprisingly far in any computery thing with mimicry.

23:18 callen: Play! is a bit better designed.

23:18 n_b: Play! (1.0 at least) and Rails are fairly similar in terms of convention doing significant amounts for you

23:18 seangrove: ioexception: Yeah, I think in the same way, I have *no idea* about developing on windows, despite having used it a ton as a child

23:19 TimMc: Well put!

23:19 callen: n_b: I've used Rails at a few different points in its evolution, my point is that your point was more true a couple years ago

23:19 n_b: it's less true these days because Rails has a really deep and very vertical stack of things you need to learn that are usually scaffolded for you.

23:19 seangrove: Meh, I love rails for what it's good at

23:20 renderful: agreed seangrove

23:20 seangrove: It'll be interesting to see if it can evolve from what it is now to where people are going though

23:20 callen: I prefer Django and Flask. more restraint, more obvious as to how it works, less magic.

23:20 renderful: magic is bad

23:20 seangrove: Never used flask, just Django and a fuck-ton of pylons

23:20 n_b: ioexception: then I've only been exposed to some very top-tier developers, but nigh every person I've worked with has started out on JVM or the CLR and later migrated to Python, Rails, or similar, typically when going from BigCo™ to a startup

23:21 callen: I went CLR -> Python professionally and I use Clojure a lot on my free time.

23:21 it's been a similar Java/CLR -> Python/Ruby migration path for most startup people I know that have past experience

23:21 n_b: Rails is a rabbit hole, no doubt, but I much, much rather come into some weirdly configured, built from mish-mash of Active* components and rack middleware ruby project than some GWT-monstrosity

23:22 callen: n_b: agreed

23:22 n_b: at least than the change/reload/recompile is faster while breaking stuff

23:25 seangrove: n_b: sounds right

23:25 Only used GWT for two weeks in a side project years ago, and wrote the gwt-rails plugin at the time

23:25 Was an absolute nightmare

23:26 squidz: seangrove: why is that?

23:26 n_b: GWT is a really great idea implemented poorly

23:26 seangrove: Mainly there wasn't any documentation at the time, almost at all. The tooling was beyond horrendous..

23:26 n_b: , to the extent that it's not really a great fit for what people expect of modern applications

23:26 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: to in this context, compiling:(NO_SOURCE_PATH:0)>

23:26 seangrove: (dec n_b)

23:26 lazybot: ⇒ -1

23:27 seangrove: Sorry, had to happen

23:27 squidz: ouch

23:27 seangrove: (inc n_b_

23:28 (inc n_b)

23:28 lazybot: ⇒ 0

23:28 squidz: seangrove: didnt know you could go negative

23:28 seangrove: Ok n_b, I hope you've learned your lesson

23:28 n_b: Don't split messages on clauses?

23:28 seangrove: Exactly

23:28 At least not when the bots are watching

23:29 n_b: Time to whip up an irssi script that escapes any messages starting with a comma

23:29 callen: (inc n_b)

23:29 lazybot: ⇒ 1

23:29 seangrove: (inc me)

23:29 lazybot: ⇒ 2

23:29 seangrove: woo!

23:30 squidz: callen: what's CLR?

23:30 callen: squidz: .NET runtime

23:30 n_b: ,(identity n_b) ;;I assume this doesn't work

23:30 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: n_b in this context, compiling:(NO_SOURCE_PATH:0)>

23:30 squidz: oh i see

23:30 callen: squidz: in a past life I was a code monkey for enterprise/insurance companies.

23:30 now I'm a pirate for a bay area startup. whee.

23:30 squidz: lucky you

23:31 seangrove: callen: If you're out here anyway, why not drag arohner's cofounder out to drinks anyway?

23:31 n_b: Going to MS for the summer, will be my first experience somewhere that uses anything MS

23:33 seangrove: n_b: I've been impressed with all my friends that have worked at MS

23:34 Though none of them were in the business area...

23:34 rbxbx: MS has a wonderful research department fwiw.

23:35 callen: seangrove: his cofounder hates me, haha.

23:35 n_b: Looking forward to it, will be on a team doing exciting-ish stuff and it should be useful experience if I go interview for APM back at Google

23:35 seangrove: callen: Really? That's impressive

23:35 TimMc: rbxbx: Can you develop on anything other than Windows in MS Research?

23:35 seangrove: He seems like a very chill guy overall

23:35 n_b: and I can stick around for Seajure :)

23:35 callen: seangrove: other than the pull request I sent him on github, the last time I had a conversation with his cofounder I ended up getting hellbanned from HN.

23:35 seangrove: he is a very chill guy.

23:35 n_b: TimMc: they do tons of non-Windows stuff

23:35 rbxbx: TimMc I'm not sure... they seem to have a lot of Haskell/functional cats over there.

23:35 TimMc: I would not be able to go back to Windows.

23:36 seangrove: callen: That can't have been a "conversation" then...

23:36 rbxbx: I'd imagine in R&D you're capapble of doing research on other platforms so long as you could bring something back to MS land

23:36 ie: F# or linq

23:36 (maybe other things as well)

23:37 squidz: Ive heard somebody say that Google uses bayes filtering the way MS uses if statements, but im not sure who said it

23:37 callen: seangrove: depends on how you look at it. it was a conversation about an IRC service that shut-down.

23:37 n_b: IME the people at Google and the people at Microsoft are equally capable at least as far as the rank and file are concerned

23:37 seangrove: callen: 'fess up, what did you say about his mother...

23:38 callen: seangrove: myself and a few others noted that the founder of the service had a habit of starting and dropping services without warning that had paying customers. rohner's cofounder took exception to this.

23:38 seangrove: Ah yes, grove

23:38 You were one of the dicks he was referring to, presumably?

23:38 callen: I don't think I was even the main one.

23:38 seangrove: amusingly, Raynes was one of the people he was arguing with as well.

23:39 I described his position on the matter as "advocating for total unaccountability on the part of startup founders"

23:39 seangrove: Leah's certainly had a weird path at this point

23:39 callen: that's what really set him off.

23:39 seangrove: throwing spaghetti at the wall is fine, that's not my problem.

23:39 seangrove: Yeah, he seemed very incensed at the time

23:39 callen: seangrove: my problem is doing it at the expense of paying (business!) customers.

23:39 they deserve to be warned in future if she starts a service designed to serve businesses that it might disappear from underneath them at any time.

23:40 if she'd handled her past projects in a more professional manner, I doubt anybody would've noticed or cared.

23:40 seangrove: Yeah, we shutdown Bushido, and spent probably a week migrating everyone

23:40 callen: she didn't, so we noticed. Then rohner's cofounder got really mad.

23:40 oh well.

23:40 seangrove: Not a single user complained in a way we didn't take care of... felt happy of that at least

23:40 callen: I'm mostly mad about my account getting hellbanned. I've been through like 4 or 5 HN accounts.

23:41 seangrove: I'm otherwise sanguine about the matter.

23:41 seangrove: are you in SF?

23:41 seangrove: I am

23:41 Yourself?

23:42 callen: seangrove: MV

23:42 seangrove: I also like Paul a lot ;)

23:42 Ah, I lived there for ~2 years

23:42 TimMc: Molybdenum Valley?

23:42 * technomancy should get hellbanned from HN

23:42 callen: I like Paul, he just holds opinions I'm not going to coddle or countenance seriously.

23:42 technomancy: sounds like a good preventative measure

23:42 callen: technomancy: you're too well known

23:42 seangrove: technomancy: I can have a word for you if you'd like...

23:43 callen: I actually heard about him originally because of his compiler work.

23:43 I didn't really make the connection between his compiler work and CircleCI until he popped up in a discussion about HipHop

23:44 technomancy: I could be like giles bowkett and just redirect all HN-referred requests to a page telling them how they're jerk-faces

23:44 seangrove: arohner: There're a lot rumors about your cofoudner flying about

23:44 You might want to squash them sooner rather than later

23:44 mehwork: how do you apply a symbol to each item in a coll?

23:44 seangrove: Rumors like he cared enough to comment on hiphop...

23:44 callen: technomancy: part of the reason I mention ES off and on is that I've been able to use it in creative ways to make hard problems VERY tractable. @ bowkett: that's some dedicated trolling.

23:44 technomancy: callen: he's a remarkable man

23:44 callen: seangrove: meh, I tried @'ing him earier, he didn't respond. I think he's semi-AFK or doesn't have working notifications in his client.

23:44 technomancy: in good and bad ways

23:45 callen: technomancy: remind me why he did that?

23:45 technomancy: callen: he writes a lot of very flame-baity articles, mostly well-written but the kind of things that bring out the worst of HN

23:45 callen: http://hyperdex.org/ <--- I use ES for a similar use-case as this

23:46 seangrove: ES?

23:46 clojurebot: https://github.com/dakrone/cheshire

23:46 callen: technomancy: the only threads that don't bring the worst out of HN are about Erlang.

23:46 seangrove: elasticsearch

23:46 technomancy: remember the day of Erlang?

23:46 seangrove: Ah, ok

23:46 callen: it was glorious.

23:46 mehwork: well actually how do you map symbols to things like so '("a" "b" "c") becomes {:foo "a" :bar "b" :baz "c"}

23:46 seangrove: mehwork: zipmap?

23:47 ,(zipmap [:foo :bar :baz] ["a" "b" "c"])

23:47 clojurebot: {:baz "c", :bar "b", :foo "a"}

23:47 mehwork: yeah zipmap works darnit my question stilli sn't what i mean

23:47 Raynes: callen: Who was I arguing with?

23:47 callen: mehwork: please elaborate.

23:47 seangrove: Raynes: technomancy over clojars

23:47 callen: Raynes: cofounder of CircleCI. The grove.io thread.

23:47 technomancy: callen: I must have missed that

23:47 Raynes: callen: Oh, yeah, that one-can-short-of-a-one-pack guy.

23:47 callen: Raynes: I'm the Gandalf of remembering HN threads.

23:48 Raynes: Yeah, that guy was about as smart as as box of hair.

23:48 callen: Raynes: LOL

23:48 seangrove: Hah, ouch

23:48 * callen is laughing so hard he's shrieking

23:48 mehwork: zipap only maps 1:1, and i need to create a nested map as i do it, such that: '("a" "b" "c") becomes: {:foo {:foo "a"}, :bar {:bar "b"}, :baz {:baz "c"}}

23:48 TimMc: Raynes: See, this is why Alabama is allowed.

23:49 Raynes: It's just that I like Leah and didn't mean anything by it, but by the 3rd or 4th abandoned startup, you start to wonder if you should really rely on anything she does. *shrug*

23:49 TimMc: The South has some pretty good sayings.

23:49 Raynes: It's great for her startup lifestyle, not so great for users of said startups.

23:49 seangrove: TimMc: I sitll think it's a stretch to argue the existanace of the south is justified

23:49 callen: My position was identical to Raynes'

23:50 Raynes: seangrove: So what was I arguing with technomancy about clojars for?

23:50 seangrove: Raynes: sorry, just a bit of trolling

23:50 callen: Raynes: he was kidding

23:50 mehwork: the south deserves to exist. the people in it are another question ;p

23:50 TimMc: seangrove: It's also very scenic.

23:50 callen: Raynes: the argument mentioned was the grove.io thread.

23:50 Raynes: Well, I actually did complain about technomancy making the releases repo.

23:50 technomancy: we got bit by grove.io disappearing and are stuck on campfire =(

23:50 it's ... not a good piece of software.

23:50 callen: technomancy: haha oh god, point proven.

23:50 seangrove: technomancy: Stripe might release their system

23:50 callen: technomancy: most people make-do with campfire by using propane.

23:51 technomancy: callen: unacceptable

23:51 seangrove: It's an irc server witha web frontend as well

23:51 Raynes: But then I realized it didn't effect me at all as long as I put information in my project.clj that I should have put there anywhere.

23:51 callen: technomancy: if I made a grove.io clone, would your company pay for it?

23:51 technomancy: for many reasons, foremost of which is that it's not Emacs

23:51 Raynes: technomancy: I've yet to figure out why people don't just get a private channel on any given IRC network.

23:51 Unless you're Red Hat.

23:51 technomancy: callen: the problem isn't a lack of alternative, it's that I blew my "get me the hell away from campfire" capital on a lost cause =\

23:51 callen: Raynes: my company did that initially.

23:51 Raynes: Who has like 400 IRC channels on their private network.

23:51 callen: technomancy: that's sad. Really sad.

23:51 technomancy: Raynes: because "freenode" isn't "free as in we host your infrastructure for you"? =)

23:52 callen: we actually switched away from freenode because it was too unreliable.

23:52 Raynes: technomancy: I set up an ircd once. I would not recommend it.

23:52 TimMc: Running a private IRC server is like... the easiest thing, right?

23:52 callen: TimMc: if you're competent at the whole unix and editing text files thing, sure.

23:52 technomancy: Raynes: we used subrosa (written in Clojure) at my last job and it was awesome.

23:52 Raynes: technomancy: The only people who say setting up an IRC network is easy are people who have already done it a couple of years ago and blocked out the memory of it.

23:52 TimMc: callen: Wait, there's no GUI? :-O

23:53 callen: technomancy: subrosa is abandoned, no?

23:53 Raynes: callen: If you're competent at editing text files with settings that seem nearly meaningless.

23:53 But are super important.

23:53 technomancy: callen: it's not actively developed, but it's in active use every day by its author, which counts for something?

23:53 Raynes: Well, I'll be honest, setting up the server is fairly simple. Linking services and other servers with it is not.

23:53 callen: technomancy: fair enough.

23:53 technomancy: Raynes: the problem is using software that's not written in lisp.

23:54 ugh; flashbacks to configuring znc--so horrible

23:54 Raynes: technomancy: The problem is using software with custom configuration languages.

23:54 technomancy: faux-xml

23:54 is. the. worst.

23:54 worse even than .ini files

23:54 Raynes: Dear people, you do not need a custom configuration language. Use a good language.

23:54 rking: Well, what's the solution to the config problem?

23:54 technomancy: Raynes: yes: if your programming language isn't sufficient for a config file language I don't even want to talk to you; just leave the premises at once or I'll call the ~gourds on you

23:54 seangrove: Or use a non-deterministic config language

23:54 callen: I've actually been giving thought as to how to make a reliable distributed IRC network

23:54 rking: Raynes: OK so how do you get it from that language to your language?

23:55 Raynes: rking: In Clojure, my configuration language *is* my language.

23:55 rking: Everybody has to write configs in the language that's interpreting them? What does C do, then?

23:55 Raynes: I was kinda implying you shouldn't do it in C. :p

23:55 rking: Raynes: Do you have an example of software that uses Clojure as a config?

23:55 technomancy: inc

23:55 Raynes: rking: Plenty of my own software, and pretty much everyone elses.

23:55 Did I offend you or something somehow?

23:55 seangrove: technomancy: dec

23:55 rking: Raynes: URL to config files?

23:56 callen: anyone seen Nginx or Varnish config files?

23:56 Raynes: I think I offended him. :(

23:56 mehwork: Django uses python as a config language

23:56 callen: it's a mini-language just for configuration. Hilarious.

23:56 amalloy: rking: every project.clj file ever, is leiningen's configuration, in clojure

23:56 technomancy: callen: nginx doesn't feel so bad just because it's usually compared with apache

23:56 TimMc: I write my Piet config files in Piet, what's the problem?

23:56 callen: technomancy: I know...god I hate configuring apache.

23:56 amalloy: (inc piet)

23:56 lazybot: ⇒ 1

23:56 Raynes: rking: Well, there is lazybot. It uses Clojure code for configuration. The plugins might as well be configuration because they are dynamically loaded at runtime.

23:57 I mean, I'm not sure what I have to prove.

23:57 callen: TimMc: I prefer Mondrian.

23:57 Raynes: Clojure is perfect for Clojure configuration.

23:57 It's just natural.

23:57 Python and Ruby and even Haskell can do it too.

23:57 TimMc: Raynes: My entire source tree is config for the JVM.

23:57 mehwork: "code being data"

23:57 Raynes: See xmonad for Haskell.

23:57 callen: TimMc: HAHAHAHA

23:57 TimMc: the people who've worked in "enterprise" will get your joke :P

23:57 Raynes: But seriously, I promise, it's possible, people do it, it's better.

23:57 TimMc: My hard drive is source for the CPU.

23:57 *config

23:58 Raynes: xmonad is a great example.

23:58 technomancy: seangrove: I actually think the suckless way is great for C programs

23:58 TimMc: callen: I'm not sure I get it from that perspective, jsut from a comp arch perspective.

23:58 Raynes: I'd also bet that you can even do something like it in C.

23:58 mehwork: if the world only makes sense to you in java/xml then the world might has well have just ended today afterall

23:58 rking: Hahaha

23:58 technomancy: seangrove: you want to reconfigure it? recompile it. it only takes 5s because it's small =)

23:58 rking: https://github.com/flatland/lazybot/blob/develop/.lazybot/config.clj

23:58 *That's* supposed to be an end-user facing config lang?

23:58 technomancy: anything larger and you have no business using C =)

23:58 Raynes: Uh

23:58 mehwork: rking: that's what admin interfaces are for

23:59 rking: Sorry, I'm new enough to clojure that I didn't realize that was as good as it gets.

23:59 Raynes: I...

23:59 technomancy: json would be OK for config if it weren't for the insane refusal to support comments

23:59 Raynes: I didn't...

23:59 TimMc: rking: Looks fine to me.

23:59 ibdknox: Raynes: make better configs :p

23:59 geez

23:59 Raynes: I never said that was as good as it gets, Mr. Sir. Furthermore, end-user configurations?

23:59 TimMc: technomancy: Crockford is pretty weird about JSON.

23:59 rking: mehwork: Then the serialization format doesn't matter if you have an admin interface. Could be a gzipped wad of ints.

23:59 callen: rking: it would seem you haven't done much Clojure development.

Logging service provided by n01se.net