#clojure log - May 18 2012

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

0:00 fil512: it kinda feels like you have to be above-average smart to develope in it, and it's easy to write code that's hard to understand...

0:00 PeregrinePDX: I don't think I am above average smart for a programmer.

0:00 I'm also pretty new to clojure and it takes me awhile but I can figure out a lot of clojure.

0:01 ivan__: fil512: i think you have to be open minded more than smart - so many developers never seem to want to try anything new

0:01 fil512: I want to have the confidence that anyone from any team could walk up to the clojure code and understand what it's doing. but I worry this is not the case with clojure the way it is with more structured languages like java

0:02 I work on million dollar software projects. Our code has to be maintainable.

0:02 I'm always keeping an eye out for the next big thing.

0:02 Clojure is a candidate right now.

0:03 But is it a "business grade" programming language.

0:03 That's what I'm trying to figure out...

0:03 ivan__: fil512: should watch the infoq presentation the guardian did on there move to scala - its maybe not directly related to clojure but it was interesting about java guys trying something new

0:04 fil512: I've heard disastrous things about scala. Definitely not an option for us.

0:04 My impression of scala is some guy got impatient with java not having all the stuff he wanted in a language and so he invented a way to extend java so he could put all that cool stuff in...

0:04 ivan__: haha i dont think thats true at all

0:05 fil512: clojure feels orders of magnitude better thought out than scala

0:05 variable immutability as a way to deal with multi-core

0:05 super-clean kernel

0:06 when the robot overlords take over the world, they will code in clojure

0:06 brehaut: immutable data is a way to deal with reason in general. multi-core happens to fall out of that

0:06 but its far more valuable than just that

0:06 ivan__: clojure is nice - but scala has its good points to. One of them is that its easy for java guys to get started

0:07 eggsby: ya ivan__

0:07 fil512: C# is easy for Java guys to learn too. That's not a criteria for me.

0:07 eggsby: we have a lot of scala guys at work, only a few clj

0:07 ivan__: yeah, immutable data is the way to go - scala provides nice things for that too

0:07 fil512: been good chatting

0:07 gtg

0:07 thanks for the help!

0:08 ivan__: seeya

0:08 idk, im all for clojure - but if you have 120 guys that dont know it, but know java - it seems like it would be a big deal to move to it heh

0:08 eggsby: I think the biggest practical difference between clojure and scala, while both can mostly implement the features of the other without too much pain, if you switch from java to scala you don't need to learn anything, just a bit of syntax

0:09 mtkoan: I shudder at the thought of 120 programmers

0:09 eggsby: but if you switch to clojure, you'll have to completely change how you think about writing programs

0:09 i.e. you can have 10 years of java experience and pick up scala in a few days, clojure would probably take a few weeks/months if you haven't had prior FP experience

0:09 ivan__: there arent many scala guys at work (and no clojure), but i can get away with using scala as long as I keep it nice and clean and dont try and do stuopid stuff with type system - java guys can read the code

0:10 eggsby: if you are using groovy you could probably switch to scala without people really noticing :p

0:10 ivan__: eggsby: yeah - for me I started by writting scala in a very java way, over time i learnt how to work with immutable data, fp stuff etc

0:11 not that i want to rant on about scala in #clojure haha - but i was just finding it wierd the objections that guy has to it

0:11 eggsby: I liked fogus' talk about macros, where he implemented BASIC as a DSL in scala, then showed how because it didn't have macros parts of the language peeked through in the implementation

0:12 ivan__: this was before 2.10?

0:12 (2.10 has macros)

0:13 macros in scala dont make a lot of sense to me yet - ive seen one example but i understood the use in clojure a lot easier

0:13 eggsby: ah, must've been

0:13 but ya lol @ scala not being enterprise grade, hi twitter

0:14 ONE MILLION DOLLARS

0:14 :)

0:14 ivan__: The Guardian... they started out by using scala for doing the java test code - to make it interesting

0:14 would be cool if i could do the same thing with clojure

0:15 eggsby: Clojure has been an enlightening experience. Kind of a lesson in the power of abstractions

0:16 I've been making the finishing touches to a system I built for work in clojure, the architecture from it was lifted from ring's middleware implementation, seemed like a good way to model transformations over data... then I ran into this article today: stuartsierra.com/2012/05/16/syntactic-pipelines

0:16 I had a lot of the same problems, repeated logic deep inside function bodies, seeing that repetition just plucked away with macros is so beautiful

0:17 I guess any language with metaprogramming capabilities can make something like that happen, but it just seems so elegant/general in clj/lisp

2:09 Raynes: People should be talking in this channel.

2:10 PeregrinePDX: Sorry I was reading Clojure Programming

2:14 I suppose I could put my random thoughts regarding learning clojure in here rather then in a PM window to someone I know.

2:14 But really I don't know that people are that interested that I find the existance of empty as a pleasant surprise.

2:20 Although my cat seems to think learning clojure is a poor choice of my time and it would be better spent petting her.

2:21 Raynes: PeregrinePDX: It is late enough and quiet enough that your random thoughts should be socially acceptable.

2:21 And if they serve to keep me entertained, rest assured that I will hold off the beasts.

2:43 PeregrinePDX: Oh I like the existance of transients although I imagin some people prematurely optimize things by using them too much.

2:50 amalloy: PeregrinePDX: i don't think that happens very often

2:51 clojure is very...firm on the topic of immutability, and nobody uses transients just for fun. records, now...those get used prematurely all the time

2:51 PeregrinePDX: Then clojure programmers are far more disciplined then some of my former coworkers.

2:52 amalloy: as a nice aside, i (and probably you) often write code that benefits from transients without having to think about it: ##(doc into) uses a transient under the hood

2:52 lazybot: ⇒ "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

2:52 * PeregrinePDX nods.

2:52 PeregrinePDX: Yeah, the clojure programming book I am reading was explaining that about into.

3:02 aperiodic: speaking of records, i have a thing (bezier curve) that i want to be able to use like a map is basically every way besides when it's invoked

3:02 what's the easiest way to do that?

3:03 s/is basically/in basically/

3:20 amalloy: aperiodic: maybe (defrecord Bezier [] clojure.lang.IFn (invoke [this arg] ...))?

3:30 kral: namaste

3:33 aperiodic: amalloy: is that sufficient? i remember hearing something about a gotcha if you don't implement all the arities for invoke in BG's clojure/west talk, but it might've been minor

3:33 amalloy: i guess you probably also have to implement applyTo

3:36 aperiodic: i should really get in the habit of checking clojure's source

3:38 amalloy: good habit to have

3:41 aperiodic: yeah, i'm just a little irrationally reluctant about reading java, and the style will probably take me a little getting used to

5:50 xumingmingv: can some one explain this: http://stackoverflow.com/questions/4921566/clojure-returning-a-vector-from-an-anonymous-function

5:50 (explain the accepted answer)

5:50 i know list is function call

5:51 vector is also function call?

5:52 babilen: &([1 2 3] 0)

5:52 lazybot: ⇒ 1

5:52 Borkdude: xumingmingv: ##([1 2 3]) ;; calling a vector from function position with no args

5:52 lazybot: clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector

5:52 Borkdude: xumingmingv: ##(vector 1 2 3) ;; calling the vector "function" to construct a vector

5:52 lazybot: ⇒ [1 2 3]

5:52 babilen: xumingmingv: You can use (vector index) to get an element at the given index

5:54 xumingmingv: ah, ok, i got it

5:54 do you guys feels it confusing?

5:55 Borkdude: xumingmingv: anonymous function with #-notation tricked me before as well

5:55 babilen: Not much -- The same works with maps (i.e. ##({:a 1} :a} == (get {:a 1} :a)

5:55 Borkdude: xumingmingv: ,((fn [] [1 2 3]))

5:55 xumingmingv: ##((fn [] [1 2 3]))

5:55 lazybot: ⇒ [1 2 3]

5:56 Borkdude: xumingmingv: with this notation #( … how to return a vector directly? I think you can't )

5:57 xumingmingv: a literal that is. by calling the vector "fn" you can

5:57 ,(#(vector 1 2 3))

5:57 clojurebot: [1 2 3]

5:59 xumingmingv: thanks you guys, Borkdude babilen

6:00 Borkdude: wow this is ugly… ##(+ 1 2 3 nil)

6:00 lazybot: java.lang.NullPointerException

6:03 myarray: please, can anyone explain, what is the motivation of max-key / min-key functions in returning the *last* match instead of first?

6:03 (apply max-key count [[1 2] [3 4] [5] [6 7] [8]])

6:04 Borkdude: ,(doc max-key)

6:04 clojurebot: "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest."

6:04 Borkdude: myarray: it probably uses reduce

6:05 myarray: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4419

6:06 Raynes: Well, it has too...

6:06 I mean, if you want a sane algorithm.

6:06 Borkdude: Raynes: yes

6:06 Raynes: It has to go through all of them to know what the greatest is, so it makes sense for it to return the last greatest it finds.

6:07 Though it could return the first it finds.

6:08 Borkdude: Raynes: or all the maxima

6:09 (what is the plural of maximum in English? maximums?)

6:10 Raynes: &(apply (fn [k & xs] (reduce #(if (> (k %2) (k %)) %2 %) xs)) count [[1 2] [3 4] [5] [6 7] [8]])

6:10 lazybot: ⇒ [1 2]

6:11 Raynes: myarray: ^

6:11 If you need that behavior.

6:13 * Raynes goes to sleep

6:17 Borkdude: Raynes: sleep well

6:17 TEttinger: did you see my refactoring yesterday of your function?

6:19 myarray: &(apply max-key count [[1 2] [3 4] [5] [6 7] [8]])

6:19 lazybot: ⇒ [6 7]

6:19 myarray: it returns the last matching element

6:20 imho its not very intuitive

6:20 Borkdude: myarray: it is because it has to traverse all of the collection

6:20 myarray: should be [1 2]. I am curious why it is so, what is the idea behind returning the last

6:21 Borkdude: myarray: see the source https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4419

6:21 myarray: if you want it the other way, use Raynes his variation

6:21 myarray: no its not. Well, it does have to traverse, but it can keep the already found max value if it has found the same max value

6:21 Borkdude: myarray: this is what Raynes his version does

6:23 myarray: My question is not "how to". My question is why it does it, what is the motivation?

6:24 other FP languages that have max-key like functions return the first match if there are few equal max values

6:24 is it some kind of Lisp behavior legacy?

6:25 Borkdude: myarray: I think with these kinds of functions you should not depend on order anyway, so what's the big deal?

6:26 myarray: it's just a choice. the version in core is a short elegant version, which produces a valid result

6:26 myarray: There is only one character in max-key function that should be changed in order to get the intuitive behavior.

6:27 TEttinger: Borkdude, yes! thanks for that.

6:27 babilen: I don;t necessarily find that behaviour to be more intuitive. max-key makes no promises regarding the order.

6:29 myarray: well, may be it should :-)

6:29 consider a solution for this task http://www.4clojure.com/problem/53

6:29 Borkdude: myarray: you mean replace > with >= ?

6:30 myarray: one of them would be building a sequence of all possible seqs and then getting the first max

6:31 otherwise, you have to "reverse" it before. But returning the first "winner of the hill" seems to be more intuitive to me

6:31 Borkdude: yes

6:31 TEttinger: Borkdude, just so you know, it won't compile as-is

6:31 myarray: Borkdude: or swapping left and right args

6:33 Borkdude: it depends on reduce1 which private, if you are trying to make a copy of max-key in your own ns, you should have your reduce1 as well

6:35 Borkdude: TEttinger: ah yes, you have to reverse the order of the function definitions

6:36 TEttinger: Borkdude, yeah, all it took was that, and changing a call to left? to left-col?

6:39 Borkdude: TEttinger: ok changed it

6:39 TEttinger: I think the algorithm can be much simpler though ;-)

6:39 TEttinger: thanks, yeah

6:40 how do you think it would, though?

6:41 oh. i think i have a bug already

6:41 (path-in-matrix 0 11) will walk over a corner, which it isn't supposed to do

6:42 Borkdude: TEttinger: I don't know what your algorithm is supposed to do exactly

6:42 TEttinger: yeah, it is meant to be a highlighter for a 1D-imitating-2D vector

6:43 so it should highlight the line between a starting corner square and a target square

6:43 Borkdude: TEttinger: it should walk also in diagonals or smth?

6:43 TEttinger: so the shortest path?

6:43 TEttinger: i could use bresenham, but for some reason i thought making one turn would look better to the user (which is a goal in this)

6:44 and with orthogonal-only movement, it currently does highlight the shortest line, except when it walks over corners

6:44 Borkdude: TEttinger: good luck, the only thing I wanted to point out is that making a giant function into more smaller functions is easier to test =)

6:44 TEttinger: ah ok

6:45 i will look into how to implement bresenham's line algorithm in clojure, i think it isn't very complex

6:48 mduerksen: myarray: i think the preference of max-key is more intuitive the way its implemented now: left-to-right, just like e.g. merge. but intuition aside (which may vary), it should be explicitely written in the doc.

6:53 hyPiRion: Would jumping directly over Leiningen 1.x to Leiningen 2 be smart? I haven't used any, and I'm going to port a 1.2 project over to 1.4.

6:53 Borkdude: haha

6:54 technomancy: http://twitpic.com/9mc9aw ;-)

6:54 hyPiRion: Borkdude: yeah, I noticed as well. :p

7:00 Well, I cannot see why it shouldn't be smart.

7:02 xumingmingv: a silly question

7:02 we know that we use ; for comments in clojure

7:02 why most clojure code use ;; ...

7:02 double ;

7:03 ejackson: haha, I guess due to // from java

7:04 and still having ; mean line end, so not wanting to put it at the front of a line :)

7:04 hyPiRion: Lisp convention. ; is for comments in code, ;; is for comments before/after code

7:04 ejackson: well that makes more sense !

7:05 xumingmingv: after code?

7:06 hyPiRion: As in, after the closing paren of an expression. E.g. after a defn.

7:29 TEttinger: gah, why is there no floor function? org.clojure/math.numeric-tower has some issue that prevents floor from working

7:31 http://pastebin.com/Ha8vkKsS my lengthy error

7:31 Borkdude: TEttinger: ##(int 3.567) ?

7:31 lazybot: ⇒ 3

7:31 TEttinger: ,(int 15/2)

7:31 clojurebot: 7

7:31 TEttinger: oh ok

7:31 thanks

7:34 Borkdude: ,(* (int 3.5) 2.3)

7:34 clojurebot: 6.8999999999999995

7:37 babilen: TEttinger: ##(Math/floor 42.23)

7:37 lazybot: ⇒ 42.0

8:16 Borkdude: sometimes I wonder about clojuredocs, if I search for "def", why doesn't "def" turn up.. http://clojuredocs.org/search?x=0&y=0&q=def

8:19 foxdonut: Borkdude: strange indeed.. it shows up in the autocomplete but not in the search results :/

8:20 Borkdude: foxdonut: I have had this with other searches as well

8:21 foxdonut: also the autocomplete representation is broken in Chrome on my system

8:22 foxdonut: Borkdude: works on Chrome/Ubuntu and Chrome/Mac.. what are you on?

8:23 Borkdude: foxdonut: Chrome / OSX

8:23 foxdonut: http://twitpic.com/9md5xd <-- I get this

8:24 foxdonut: try typing a "d", let the autocomplete come up and then press "e"

8:24 foxdonut: Borkdude: huh. that's whacked.

8:25 Borkdude: foxdonut: you don't get this?

8:25 foxdonut: Borkdude: I don't get any truncated autocomplete, but doing the d-then-e thing makes 'def' not show up.

8:26 Borkdude: foxdonut: with me the autocomplete results get positioned over the search box

8:51 solussd_: Could anyone tell me why this won't compile (I get a java.lang.InstantiationException when it tries to compile the macrolet form): https://www.refheap.com/paste/4fb64515e4b0225aed0333ec

9:01 hyPiRion: solussd_: I don't know why, but I would've tried to get rid of that macro: https://www.refheap.com/paste/4fb647aae4b0225aed0333ed

9:03 I screwed up the indentation, but the idea is that if you're able to make a macro into a function by using apply, then do that istead.

9:04 neotyk: solussd_: where did you get macrolet from, I want one as well

9:06 TimMc: foxdonut: The autocomplete and search results most notably differ on things with hyphens.

9:06 solussd_: macrolet is in clojure.tools.macro

9:07 hyPiRion: I cant use apply-- the args list is conditional on the args, and simply building the arg list and then applying the command is no better than the macro. I like macrolet. :)

9:08 I'm concerned about what looks like perfectly valid code not compiling.. :/

9:14 foxdonut: TimMc: ic

9:15 mmarczyk: solussd_: actually the expansion seems to depend on the runtime values of dest-name and submodule-recursive -- so, not valid code at all

9:15 solussd: ^

9:16 solussd: CLHS says "the consequences are undefined if the local macro definitions reference any local variable or function bindings that are visible in that lexical environment" (i.e. the lexical environment where the macrolet form appears) http://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm -- that applies to CL, but I'd expect the same from tools.macro

9:25 goodieboy: I'm having the problem described here: http://stackoverflow.com/questions/10289617/clojure-ring-jetty-i-am-using-lein-ring-server-how-do-i-configure-the-jetty

9:26 I have to keep using "lein ring server", so somehow I need to configure jetty within my project.clj -- I tried the example in that ^^ link, but nothing is working

9:27 anyone know how to deal with this -- summary: In development mode, jetty is giving me a "FULL HEAD" response

9:27 mmarczyk: goodieboy: http://stackoverflow.com/questions/9285096/clojure-ring-using-the-ring-jetty-adapter-large-requests-give-me-a-413-full-h/9286288#9286288

9:28 goodieboy: mmarczyk: thanks! I'll give that a shot.

9:28 weavejester: goodieboy: If you specify the configurator as a symbol, that might work.

9:29 goodieboy: e.g. {:ring {:adapter {:configurator some.config/foo}}}

9:29 goodieboy: weavejester: ahh, ok

9:29 mmarczyk: I'd still expect unquote to be necessary

9:30 but if it isn't, I'll be interested to learn that :-)

9:30 weavejester: mmarczyk: I believe the adapter arguments are passed as-is to eval-in-project

9:31 So in theory they should be evaluated.

9:32 mmarczyk: weavejester: ah, then it shouldn't matter, fns are self-evaluating currently

9:33 weavejester: mmarczyk: Yes… an anonymous function should work in theory...

9:33 michaelr525: weavejester: hi

9:34 weavejester: i don't want to bother you with this, but can you tell me whether you've seen my comment here: https://github.com/weavejester/lein-ring/issues/10

9:35 goodieboy: weavejester mmarczyk: hmm, i can't get it to work. Using :ring {:adapter {:configurator app/configure etc.. doesn't ever execute my function

9:35 weavejester: goodieboy: Which version are you using?

9:35 goodieboy: weavejester: of lein-ring?

9:35 weavejester: goodieboy: Yep

9:35 goodieboy: weavejester: 0.7.0

9:35 weavejester: michaelr525: I have, but haven't had time to look into it.

9:37 michaelr525: weavejester: ok, thanks.. i intent to tackle this problem myself sooner or later anyways, thought maybe you have an idea what could it be

9:37 weavejester: michaelr525: No idea, since I wasn't able to reproduce the original issue. Which version of Tomcat are you using, btw?

9:38 michaelr525: 7.0.21

9:39 weavejester: goodieboy: Hm, not sure why that wouldn't be working, but I haven't tested using configurator with lein-ring before

9:40 goodieboy: weavejester: ok. Using ~(prn "configure!") does work, but I guess that doesn't really mean that lein-ring is doing anything with the :configurator value, just that the prn is getting evaluated immediately right?

9:41 like this: {:ring {:adapter {:configurable ~(prn "configure!")}}}

9:42 weavejester: goodieboy: This might need a patch for it to work

9:43 goodieboy: weavejester: if you could point me in the right direction, i could attempt doing this if you'd like

9:44 weavejester: goodieboy: I'm afraid the only direction I can point you in is the lein-ring source code

9:44 goodieboy: weavejester: gotcha ok, checking that out now

9:45 weavejester: goodieboy: Out of interest, why are your headers so big?

9:46 goodieboy: weavejester: we store a lot of data in cookies, i'm assuming that's it?

9:46 weavejester: goodieboy: That's probably it.

9:52 solussd: mmarczyk: thanks!

10:06 goodieboy: weavejester: is this function called somewhere when running "lein ring server" ?

10:06 https://github.com/weavejester/ring-server/blob/master/src/ring/server/standalone.clj#L56

10:07 it looks like lein-ring recognizes :adapter here: https://github.com/weavejester/lein-ring/blob/master/src/leiningen/ring/server.clj#L27

10:08 sorry wrong link, ring-jett-adapter: https://github.com/mmcgrana/ring/blob/master/ring-jetty-adapter/src/ring/adapter/jetty.clj#L61

10:09 anyway, that config setting is getting lost somewhere along the way

10:10 jsabeaudry_: Is there any point to doing @(future (dostuff)) instead of (dostuff)?

10:14 rhc: jsabeaudry_: not that i can see, just extra overhead

10:15 jsabeaudry_: rhc, thanks for the confirmation, that was my impression too

10:19 gfredericks: (-> (dostuff) future deref future deref future deref future deref) ;; make sure

10:24 pjstadig: gfredericks: needs syntax shorthand like caadar

10:29 jsabeaudry_: hehhehe

10:34 gfredericks: googling caadar tells me nothing. This is some mashup of car and cdr?

10:34 (def caadar (comp first first rest first))?

10:34 jweiss: I think it's (car (car (cdr (car x))))

10:34 or maybe i got that backwards

10:35 gfredericks: lisp complects forwards with backwards

10:36 pjstadig: common lisp lets you use any combination of a's and d's between the c and r

10:36 gfredericks: O_O

10:36 wtf.

10:36 pjstadig: and it just becomes the composition of all the cars and cdrs

10:36 jweiss: pjstadig: you mean, even caaadadaddaddadaddddddaaaar ?

10:36 gfredericks: so you can't name anything #"c[ad]+r" because it will be misinterpreted?

10:36 pjstadig: sure i think so, i'm not sure if there is some theoretical or practical limit

10:37 llasram: Is that really true? In /LoL/, one of the things the author does is define a macro w/in which one can use any #"c[ad]+r"

10:37 Wouldn't think he'd need to do that if support already existed, but I don't know my CL v well..

10:37 pjstadig: to the hyperspec!

10:38 http://www.lispworks.com/documentation/HyperSpec/Body/f_car_c.htm#car

10:38 looks like only up to four compositions of car and cdr

10:38 gfredericks: #"c[ad]{1,4}r"

10:38 jweiss: i have some data. most of the data is fixed, iow, always evaluates to the same thing. pieces of it are not - for instance it evaluates to a timestamped string. so far i've been enclosing this literal in (fn [] ...) so that i can call the fn and get a "new" piece of data each time. but that creates an awful lot of functions to compile. i'm wondering if i can implement this where the data is consumed, maybe with protocols.

10:38 llasram: That seems... er, sensible?

10:39 hyPiRion: pjstadig: There's a practical limit. Most of the common lisp implementations is limited at around 4 or 5.

10:39 Though that being said, nothing limits implementators to have more.

10:39 gfredericks: reminds me of the generated IFn primitive interfaces or whatever that was

10:41 llasram: Oh yeah. Those make me slightly sad every time I think about them. But generating them dynamically seems pretty fraught with peril

10:43 jweiss: Like have an object which represents "the time at which you examine the object"?

10:43 misislavski: neotyk: with today's bleeding edge cljs, I'm seeing Unaught Error on robots discussed here about a month ago / CLJS-35. Do you know a workaround?

10:44 jweiss: llasram: yeah, but i don't see how i can do it. some of the data need to refer to the same timestamped string.

10:45 llasram: jweiss: Yeah, I was thinking that would make it kind of problematic... What's the down-side of having a function generate the data? Do you have a v large number of these functions being dynamically `eval`ed or such?

10:46 jweiss: llasram: as i add more data i'm adding more functions that need compiling, doesn't seem very scalable. functions seem a little heavyweight here

10:48 ibdknox: Hey folks

10:48 Borkdude: hi ibdknox

10:48 llasram: jweiss: So really your data are essentially templates? And you need something to generate the actual data from the templates? (thinking out loud)

10:48 ibdknox: I have an exciting announcement :) Light Table was accepted late to YC

10:49 llasram: ibdknox: Congratulations! And since I haven't been on #clojure since the Kickstarter project got funded, congratulations on that too!

10:49 jweiss: llasram: yeah, when you put it that way, sounds like we're talking about macros

10:49 ibdknox: can a couple people help me spread the word: http://news.ycombinator.com/newest

10:50 timvisher: hey all

10:50 ibdknox: It's important that people know circumstances have changed :)

10:50 llasram: thanks!

10:50 timvisher: how would you go about converting an io/input-stream into a byte[]?

10:50 llasram: jweiss: Wellll. Not necessarily. That might be an easy way to implement things at first, but still locks your data into executable code. I don't know -- it probably depends on the details of the data

10:50 raek: timvisher: use the read method of the InputStream class

10:51 TimMc: ByteArrayOutputStream + a pumper?

10:52 raek: (.read input-stream buffer)

10:52 timvisher: raek: recursively, i suppose?

10:52 i'm trying to understand how I would terminate

10:52 ah yes

10:52 while

10:52 jweiss: llasram: have stuff like (fn [] {:a (unique-name "joe")}) which produces a different value each time. but then sometimes i need to refer to the same thing twice: (let [x {:a (unique-name "foo")}] (dothing x))

10:52 raek: timvisher: how much data do you need to read each time?

10:53 timvisher: few megabytes

10:53 or less

10:53 jweiss: sorry llasram forgot to add (dootherthing x) :)

10:53 raek: do you need to fill the buffer completely, or do you just want to read what's available?

10:53 timvisher: only what's available

10:53 gfredericks: if he wants a byte[] doesn't he have to read everything first?

10:53 Borkdude: ibdknox: can I ask a dumb question, does this mean you don't need the kickstarter money anymore?

10:53 raek: timvisher: how are you using the byte-array?

10:53 timvisher: i'm trying to read a file from the web once, then turn it into both a bufferedimage as well as an md5 hash

10:54 gfredericks: ibdknox: I can take the kickstarter money if you don't need it

10:54 I don't mind

10:54 llasram: jweiss: What's the data ultimately being used for?

10:54 timvisher: i don't believe i can use just the stream anymore because one or the other would consume it

10:54 raek: timvisher: if you want to put all the bytes into an output-stream, use clojure.java.io/copy

10:54 timvisher: so my thought is to read it once an then use it both places

10:54 ibdknox: Borkdude: it's still very useful, but it is not *needed*. The project is safe. That's why I'm letting people know it's ok if for them that means they no longer feel the need to pledge

10:54 raek: ah

10:54 jweiss: llasram: functional tests. the reason i need unique values, is so I can run the same test twice, and the data being used doesn't collide with data that's already in the system under test.

10:55 timvisher: and i don't think it'll be possible for me to download the data twice, especially in quick succession

10:55 Borkdude: ibdknox: what happens if people take their pledge back and the sum gets below 200k?

10:55 timvisher: if that were possible then i could probably just stick with opening 2 streams

10:55 goodieboy: anyone know if it's possible to add repositories for "lein plugin install xxx" ?

10:55 raek: I would repeatedly fill the buffer (say 2048 bytes) using the read method and give the array (and size) to the two sinks that need it

10:56 ibdknox: Borkdude: then the project isn't funded and no money transfers

10:57 Borkdude: ibdknox: so what about Python support now, already safe as well?

10:57 raek: so something like (loop [] (let [n (.read input-stream buffer)] (when-not (neg? n) (... buffer ... n ...) (recur)))

10:57 ibdknox: Borkdude: That I'm not sure about

10:57 timvisher: seems reasonable

10:57 llasram: jweiss: Ah, so generated text fixtures? Functions actually seems a perfectly sensible way to go. Esp if you're ultimately just generating Clojure data-structures. You can compose them, refer to the same generated value multiple times... They seem pretty much perfect

10:57 Borkdude: ibdknox: and how about licensing? or will it be free?

10:58 llasram: jweiss: I guess I'm not seeing the scalability problem, unless you're creating 100ks of them?

10:59 ibdknox: Borkdude: if the KS fails a few of the details around that might change, I'm not sure. In the long run maybe it isn't worth charging for the distributions

10:59 cmiles74: Has anyone see a Clojure library for working with Hazelcast? I don't want to reinvent the wheel.

10:59 jsabeaudry_: When lein uberjar fails with a compilaiton error, it seems like I'm still in the process, is there a way to tell it to retry without C-c'ing it and restarting it?

10:59 Borkdude: ibdknox: anyway, congrats!

11:00 jweiss: llasram: i'm not sure it's a problem, just thought there might be another way. i'm ok with leaving it as is, just sometimes gets confusing as to exactly when something gets evaluated, because as i compose data, each level needs to be wrapped in a function. and then of course i need a construct to explicitly call it.

11:01 llasram: seems like lisp's quote/unquote constructs kind of do the same thing

11:03 llasram: jweiss: Do you have an example of where it gets confusing? The version I have in my head of just normal functions returning and composing normal data-structures seems fairly straightforward to me

11:04 Borkdude: ibdknox: I don'tknow the details of ycombinator's process, but I read they invest 18k and you get to be three months over there.. isn't 200k better?

11:04 solussd: dependency question: I'm using a version of (lein-marginalia dev-dependency) marginalia in my project that itself depends on hiccup 0.3.7 (in this version escape-html is in hiccup.core), in my project I use hiccup 1.0.x. Running marginalia (lein marg) results in an exception complaining about not being able to find escape-html. it seems that marginalia is using hiccup 1.0, even though it has a dependency on hiccup 0.3.7. How do I get it to us

11:04 the older hiccup while continuing to use hiccup 1.0 in my project?

11:04 ibdknox: Borkdude: there's another guaranteed 150k as well. But the value of YC isn't the money, it's the guidance, the name, and the network.

11:04 jweiss: llasram: https://github.com/weissjeffm/katello.auto/blob/master/src/katello/tests/permissions.clj#L97

11:05 ibdknox: Borkdude: those things in combination are worth untold sums of money

11:05 Borkdude: ibdknox: I guess Arc support is now closer than Python ;-P

11:05 ibdknox: lol

11:06 Borkdude: certainly not :p

11:07 llasram: jweiss: Ahhhhh. Why the nested functions? Are those actually intended to be functions in the "final" data-structure, or are they evaluated before being used as fixtures?

11:09 jweiss: llasram: well, the outer fn's need to be functions because of data like starting line 97. and the inner ones often need to be functions too, because of line 122

11:09 so the test harness needs to either take maps or functions. at both levels it has to take functions

11:10 actually the inner fn's have to be fn's no matter waht

11:11 but they can't be partials, they really have to be fn's

11:11 llasram: jweiss: The code ultimately under test consumes functions, or the existing test harness needs them to be functions?

11:12 timvisher: is it possible to clear the slime repl buffer?

11:12 jweiss: llasram: the harness is my code too, so it's not required in that sense.

11:13 timvisher: M-x slime-repl-clear-buffer

11:13 llasram: timvisher: which is bound to C-c M-o by default

11:13 jweiss: llasram: i guess there's no getting around things needing to be evaluated at runtime.

11:14 llasram: Though of course thinking about bindings always makes me unable to correctly apply them...

11:14 misislavski: Is anybody else having problems with the Uncaught error with robots.txt from clojurescript master?

11:14 I can't get my browser to connect to the repl.

11:14 timvisher: jweiss, llasram: very cool

11:14 misislavski: both chrome and ff throw: "Uncaught Error: URI file:/robots.txt is invalid for field ppu"

11:14 llasram: jweiss: Right. I think the part I'm questioning is the function nesting. It seems like the whole system would be really straightforward if you ultimately just have functions which produce fully evaluated datastructures

11:15 jweiss: You could compose those functions by having higher-level functions call lower-level ones, just like in normal code

11:15 foxdonut: who wants to be Light Table backer #5000 ?

11:17 jweiss: llasram: that's what it's doing. the inner fn's i have no choice - they really are functions no matter what, even if there's no

11:17 u

11:17 unique data in them

11:17 the test is "assign this user these permissions, then as that user, run these functions"

11:18 so the test is sort of a HOF

11:18 TimMc: foxdonut: 4,998 backers now.

11:19 foxdonut: TimMc: yeah saw that, didn't know you could back out of being a backer!

11:20 TimMc: That's what ibdknox was saying in his post, though: You can back out now, it's OK. There's guaranteed funding.

11:20 I'm keeping mine in. It's still an investment.

11:21 llasram: jweiss: Oh, ok. Well. Seems good as-is to me then :-) Or at least, I can't contribute any ideas as to how it could be simpler

11:21 jweiss: It's an interesting problem though -- curious to find out if you settle on some other way of doing it

11:22 jweiss: llasram: certainly seems possible to me that there is no better way, but i'm not totally convinced of that yet :) i'll let you know if i find anything

11:22 thanks for your time

11:23 foxdonut: TimMc: what does this YC thing imply? and why might one not be a backer anymore because of it?

11:23 gfredericks: &(->> [oh boy] quote cycle (take 10))

11:23 lazybot: ⇒ (oh boy oh boy oh boy oh boy oh boy)

11:23 pbostrom: KS backers still get early access I believe

11:23 gtrak`: ibdknox: congrats

11:24 ibdknox: gtrak`: thanks! :)

11:24 gtrak`: I'd like to do some cool startup one of these days, too :-), sounds exciting

11:25 ibdknox: foxdonut: the main thing is that before people threw in money to ensure that the project had a chance, now it does, so the circumstances under which that "investment" was made have changed.

11:25 foxdonut: ultimately getting YC is a very, very good thing for the project

11:25 TimMc: foxdonut: I know nothing about YC. :-P

11:25 pbostrom: ibdknox: just curious, did you approach YC, or did they come after you?

11:25 jweiss: i'm a little confused, KS and YC seem totally different. i thought KS was "if you really want this thing built, contribute so you can get it". and then for all the developer might care, everyone else can get it for free. YC doesn't seem like they would want anyone getting it for free.

11:25 llasram: ibdknox: OOC, was the successful Kickstarter effort a factor in getting YC?

11:26 foxdonut: ibdknox: thanks for the explanation. my contrib remains, for sure.

11:26 ibdknox: pbostrom: we applied, though the whole thing was very interesting. we'll probably blog about it at some point

11:26 llasram: definitely. Half the partners had actually contributed :)

11:27 jweiss: there's tons of potential for a business even if the platform is open source :)

11:28 rkz: ibdknox: was the interview intense or were they sold before you even walked in? did they ask you how you were going to make money?

11:28 `fogus: ibdknox: We?

11:28 ibdknox: rkz: it was rough as hell

11:28 `fogus: best friend from high school (ibdthor) :)

11:29 `fogus: ibdknox: Congratulations to both of you. Huge news!

11:29 ibdknox: rkz: they really laid into us, I found out later that was because they really liked us, but boy it didn't seem like it when we walked out of that room

11:30 rkz: ibdknox: i had an interview too, one of the most intense things I've ever done in my life

11:30 this was when all the partners were in the same room

11:31 so it was like 11 people

11:31 grilling 3 of us

11:31 questions from all directions

11:31 TimMc: How does YC work? They invest money and get partial ownership?

11:32 Is it a loan?

11:32 rkz: no, cash

11:32 mmarczyk: ibdknox: wow, congrats!!! :-)

11:32 rkz: for 5-7 %

11:32 ejackson: am i reading this correctly - KS got YC !

11:33 TimMc: yes

11:33 All of the acronyms!

11:33 ejackson: BRILLIANT !

11:33 s/KS/LT/

11:33 of course :)

11:34 TimMc: That too.

11:34 foxdonut: VFC!

11:34 ibdknox: mmarczyk: thanks :)

11:34 TimMc: LT's KS probably helped them get VC from YC.

11:34 ejackson: OK

11:34 TimMc: :-D

11:34 foxdonut: IIRC RTFM OMG WTF BBQ

11:34 RickInGA: ibdknox: congrats!

11:35 ejackson: i hope this doesn't mean Clojure loses one if its most prolific project contributors

11:35 but am thrilled nevertheless

11:35 TimMc: foxdonut: No, only DAs. (Dyadic Acronyms)

11:36 ejackson: Eh, we'll get spinoffs.

11:37 foxdonut: TimMc: so no TLA then, huh

11:37 TimMc: right

11:38 Borkdude: ibdknox: maybe you should explain now what happens to the "reward structure"

11:38 foxdonut: TimMc: RO. TF. LM. AO.

11:39 RickInGA: foxdonut: LOL

11:39 ibdknox: Borkdude: yeah, I'll be posting a second update about that

11:39 ache: ibdknox: will LT be able to support LP some time in the future, perhaps with a plug-in? (literate programming)

11:40 ibdknox: ache: there's some neat stuff you could do with an LP plugin

11:40 ache: not sure I'll be the one to build it, since I'm already stretched pretty thin

11:40 but I imagine someone will :)

11:40 ache: as long as the door's open :)

11:41 it would be a dream within a dream. congrats!

11:46 cldwalker: hi all, does leiningen support an rc file i.e. leiningenrc? I'm calling (load-file my-file) each time I start lein repl

11:47 TimMc: cldwalker: There's some sort of init.clj or user.clj in ~/.lein

11:47 One is for running code in Lein itself, the other is run for your repl session.

11:48 cldwalker: TimMc: Thanks!

11:49 bhenry: has anyone had the following problem? with :main in project.clj lein repl gives "REPL server launch timed out" but with no :main in project.clj it works fine. this is lein2

11:50 foxdonut: RickInGA: :)

11:50 bhenry: even stranger is that i can run the (-main) function defined in the :main namespace from the repl that works.

11:56 gfredericks: bhenry: it might be trying to load the repl in your main ns. Does than ns do anything interesting at load-time?

11:57 (e.g., read a config file that is missing)

11:57 TimMc: bhenry: Try increasing Lein's REPL-start timeout. I forget how...

11:58 bhenry: it reads a config file, but it's not missing. and i can run (-main) from that namespace just fine once i load the repl after deleting the :main line from project.clj

12:01 zakwilson: ibdknox: congratulations on YC. Just don't forget about Korma and stuff!

12:02 TimMc: and us!

12:03 bhenry: I used to have that problem. It's basically just slow JVM startup.

12:03 hyPiRion: ibdknox: Seems like I'm late to the party, but congratulations from me too. :)

12:04 ibdknox: thanks guys :)

12:04 y3di: holeeee shittt

12:04 gratz

12:05 ejackson: well done Chris, awesome

12:05 ibdknox: zakwilson: Korma is really orthogonal to what I'll need to be doing in the near future, so I'm going to be looking for someone to help keep it moving forward

12:05 Yeah, exciting times ahead

12:05 zakwilson: I'd volunteer, but I'm bad at SQL.

12:05 ibdknox: zakwilson: me too, don't tell anyone ;)

12:05 zakwilson: Heh.

12:06 eggsby: I showed a db friend who is learning clojure korma and he got excited

12:07 composable sql... mm

12:07 zakwilson: As he should. SQL is a really terrible language.

12:07 eggsby: meh, it's not bad or hard or anything, just limited

12:07 fliebel: ibdknox: Congrats. It seems some people wonder about Python. Are you still lurking in the HN thread?

12:07 pipeline: korma is the reason i wanted to learn clojure, no joke

12:07 zakwilson: Yes, that's why it's terrible.

12:08 pipeline: i heard about clojure a couple years ago and it sounded neat but there was no particular reason i wanted to learn it

12:08 eggsby: woah YC changed their mind about light table?

12:08 sup pipeline cobol4life

12:08 zakwilson: I can't remember why I wanted to learn Clojure now. I was using Common Lisp at the time.

12:08 eggsby: ibdknox: I thought you initially got rejected from yc?

12:08 ibdknox: eggsby: we were haha

12:09 eggsby: heh

12:09 ibdknox: eggsby: for a different idea though

12:09 zakwilson: A dev tool written in a lisp that's at the top of HN every time it's mentioned is kind of a natural fit for YC.

12:09 eggsby: pg looked at the kickstarter results... 'welp'

12:09 ibdknox: I got recognized at a restaurant the other day

12:09 this whole thing is a bit surreal

12:09 eggsby: nice

12:10 you are dev famous now

12:10 ibdknox: haha

12:10 zakwilson: I'm assuming this is in the bay area?

12:10 eggsby: you work at msft right ibdknox ?

12:10 ibdknox: used to

12:10 zakwilson: yeah

12:10 eggsby: ah

12:10 * zakwilson can't think of many other places someone would be famous for writing Clojure libraries and an IDE.

12:11 llasram: zakwilson: That's funny -- I too forgot for a while what had motivated me to learn Clojure in the first place. I'm now pretty sure it was Yegge's forward to /JoC/, although I couldn't tell you why exactly

12:11 eggsby: Did they let you use clojure there...

12:12 llasram: s,forward,foreword,

12:28 gfredericks: if ibdknox is famous, then I am famous because I am in the same IRC channel he is. So I will henceforth expect recognition.

12:30 zakwilson: I don't want to be famous. Just rich.

12:31 TimMc: zakwilson: Best is to be rich but not famous. Then people don't ask you for money.

12:31 zakwilson: Yeah, but I'd buy a Ferrari and ruin it.

12:32 gfredericks: I didn't ask for fame, but here I am having to deal with it anyways.

12:32 jodaro: i can't complain, but sometimes i still do

12:33 zakwilson: I said Ferrari, not Maserati!

12:33 gfredericks: thanks ibdknox for ruining all our lives. damn paparazzi won't leave me alone.

12:33 ibdknox: 's my job. Making the world a little bit more awful one blind step at a time :D

12:34 gfredericks: it's nobody's business which movie star I'm marrying this month

12:36 wink: gfredericks: that's the quick route to "not having money"

12:37 zakwilson: So I came up with this idea for a Clojure-inspired replacement for C. Should I quit drinking?

12:37 gfredericks: what would it take to make the CLJS compiler emit C? just a GC impl?

12:38 zakwilson: No idea, but that's far from what I have in mind.

12:38 jodaro: either quit drinking, or drink more

12:39 zakwilson: Actually, I think that would be hard. CLJS uses Google's java->js thing, IIRC.

12:39 gfredericks: zakwilson: if someone needs the performance of C can they afford all the dynamicity and immutability?

12:39 yoklov: zakwilson: no, it doesn't

12:39 llasram: zakwilson: Basic idea has been done, if I understand. I'm trying to find it...

12:39 zakwilson: jodaro: http://xkcd.com/323/

12:39 yoklov: zakwilson: it uses googles js->js optimizer

12:40 progo: gambit-clojure is in the works

12:40 llasram: zakwilson: Here we go: http://voodoo-slide.blogspot.com/2010/01/amplifying-c.html && https://github.com/deplinenoise/c-amplify

12:41 jodaro: hah

12:42 zakwilson: llasram: yeah, I remember something called SC that was, I think similar to that.

12:43 jodaro: hah

12:43 todays xkcd is good

12:43 zakwilson: Anyway, what I have in mind is slightly more ambitious than just compiling to C or doing C with Lisp syntax, but less ambitious than trying to do systems programming with Clojure semantics.

12:43 llasram: What's the middle ground?

12:44 krawitz: hi, does anyone knows a convenient way to parse multipart responses in clj-http, except using commons-fileupload? i found only functions to make multipart requests, but not to parse responses. :-(

12:44 TimMc: zakwilson: Taken a look at Rust, by the way?

12:46 zakwilson: Clojure-like syntax, avoidance of complecting whenever possible, LLVM backend, static typing (but the option of an unchecked cast if you really need it), pointers, ad-hoc hierarchies... just some brainstorming at the moment.

12:46 ibdknox: we should just do LLVM clojure :)

12:49 llasram: +1

12:49 zakwilson: I like that idea, but so much Clojure depends on Java libraries.

12:54 llasram: zakwilson: Well, ClojureScript and clojure-py are having a go of it

12:55 Maybe start by creating a native-feeling C FFI layer which works in JVM Clojure by dynamically mapping to JNA, but could directly generate native code for an LLVM version

13:03 TimMc: And since we've seen LLVM compile to JS...

13:03 We could run Clojure in the browser! :-D

13:05 pjstadig: llasram & zakwilson: there's also this http://nakkaya.com/2011/06/29/ferret-an-experimental-clojure-compiler/

13:11 TimMc: "Since there is no support for vectors, they are converted to lists."

13:12 Ummm... there goes most Clojure code right there.

13:12 zakwilson: Wouldn't any of many dynamic array implementations do for that?

13:13 gfredericks: TimMc: most?

13:14 TimMc: zakwilson: Not if they use mutation...

13:14 gfredericks: does it mean vectors in code or vectors the data structures?

13:15 TimMc: Presumably the data structure.

13:15 zakwilson: Well, there is that. I think compiling Clojure to C or C++ sounds like a terrible idea, personally.

13:40 dnolen`: ibdknox: congrats on YC12!

13:40 ibdknox: dnolen`: thanks!

13:50 dnolen`: ibdknox: your talk for Strange Loop looks cool :)

13:50 ibdknox: did he post it?

13:51 ah he did

13:51 :)

13:52 gfredericks: there are a lot of SL talks O_O

13:53 technomancy: they should just make it a full week conference

13:53 dnolen`: gfredericks: yeah they run like 3 tracks or something.

13:53 hiredman: sl is totally sweet

13:53 technomancy: I think it was more like six tracks last year

13:53 gfredericks: ibdknox: the "Kodowa" link under your name goes nowheres

13:53 yes it was like six

13:54 my favorite six talks were all at the same time

13:54 ibdknox: hm

13:54 dnolen`: technomancy: heh, misremembered.

13:54 Licenser: ibdknox congrats to the LightTable startup :)

13:54 technomancy: it's wild

13:54 clojurebot: It's greek to me.

13:55 technomancy: that too

13:55 ibdknox: gfredericks: there's nothing there yet anyways: http://kodowa.com/

13:57 zakwilson: ibdknox: your stuff is always so pretty.

13:57 ibdknox: I have on idea what that site looks like on a non-mac

13:57 probably pretty shitty

13:57 lol

13:58 gfredericks: pritty shetty

13:59 ibdknox: man the reddit community is so depressing

13:59 solussd: ibdknox: congrats, btw. :D Can't wait to play with light table

13:59 ibdknox: well, sounds like you'll get to play with some of it in not too long :)

14:03 zakwilson: Yes, reddit can be depressing. I've been there for nearly seven years and moderate a largish subreddit. Did I mention I drink?

14:03 technomancy: 21st-century slashdot

14:03 solussd: currently using emacs/swank- i don't know if I can untrain myself of paredit mode. wonder if codemirror supports something similar. :)

14:04 zakwilson: reddit actually did replace slashdot for me, so... yes.

14:04 technomancy: slashdot was never that slow though

14:04 TimMc: Ugh, being a moderator kind of sucks.

14:04 technomancy: well, maybe it was and I just didn't notice because everything was slow back then

14:05 zakwilson: I wonder if I pointed a text classifier at the reddit API if I could stop moderating by hand...

14:05 gfredericks: TimMc: I bet it's more fun to be an extremerator

14:07 neotyk: dnolen`: attached reduced patch to cljs-204

14:09 dnolen`: neotyk: it looks good. Will apply later today.

14:13 TimMc: gfredericks: There are subreddits like that.

14:14 zakwilson: One of these days I will write a ROBOT9000 bot that has reddit mod credentials.

14:15 weavejester: Does anyone know of a good way to block until a trigger in Clojure?

14:15 technomancy: weavejester: promise is good for that

14:15 hiredman: a queue?

14:15 weavejester: technomancy: Yeah, but a promise only works once

14:16 technomancy: sure

14:16 LauJensen: Evening gents

14:16 technomancy: a seq of promises =)

14:16 weavejester: I was thinking a lazy seq or a promise in an atom that keeps changing

14:16 zakwilson: TimMc: that could be hillarious. I've done quite a bit with text classification lately. Even used it to write a chat bot.

14:16 technomancy: a queue would be better I think

14:16 weavejester: A queue isn't really what I want because each trigger resets the event.

14:17 hiredman: resets the event?

14:17 weavejester: I basically want to block until a file has been changed, or until a timeout.

14:17 hiredman: sounds like a queue to me

14:17 weavejester: So I don't care how many files have been changed

14:18 hiredman: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/LinkedBlockingQueue.html

14:18 weavejester: But if I get 10 file changes all at once I don't want to keep triggering the refresh.

14:19 Maybe I just want a lock

14:19 hiredman: you have a source of events > queue > a consumer of the events, which component has the responsibility to throttle?

14:19 zakwilson: pg says "When we realized that multiple YC partners had already independently contributed to the Kickstarter project because they wanted to use Light Table themselves, it was not a hard decision."

14:20 I'd contribute too if I wasn't poor.

14:20 weavejester: I was thinking of having a thread that watches a filesystem, and then to raise events when something changes.

14:21 And then I'd have a route that blocks until a file is changed, or until a timeout.

14:21 nDuff: Hrm.

14:21 mebaran151: weavejester: have you seen the WatchService in JRE7?

14:21 nDuff: Looks like shutting down swank-clojure and starting a new thread later is still reusing some state (particularly, a classloader)

14:22 hiredman: weavejester: it really sounds like a queue to me, you just have a particular consumer that has sme throttling requirements

14:22 weavejester: mebaran151: I don't really want to rely on Java 1.7...

14:22 y3di: dnolen`: where did you see chris's SL talk? I can't seem to find it

14:22 hiredman: so the consumer can look at the time from the "file modified" event from the queue and decide "well the last one was less than M minutes ago, so I will do nothing"

14:22 mebaran151: weavejester: a quick google found an Apache port that is supposed to be pure java

14:23 Apache VFS

14:23 * nDuff is reloading a JIRA plugin written in Clojure; everything else works, but swank after the restart complains about NoClassDefFoundError: clojure.lang.AFunction

14:24 weavejester: mebaran151: I'll look into that

14:25 mebaran151: it doesn't give you resolution as precise as the WatchService, but its DefaultFileMonitor polls once a second, and I think you can register multiple files too

14:26 weavejester: mebaran151: I think it would be easier for me to use ibdknox's watchtower

14:26 I'm just not certain what's the best way to block...

14:27 mebaran151: weavejester: watchtower looks neat

14:27 couldn't you just do a promise and deliver it from the on-change handler?

14:28 weavejester: mebaran151: Yep, and that would work once… but when a promise has been delivered, the value doesn't change.

14:29 I guess...

14:29 What I want to say is "has the filesystem changed since time X"

14:29 That could be the promise.

14:31 neotyk: dnolen`: thanks

14:31 mebaran151: throw the promise in an atom and reset it everytime?

14:32 weavejester: mebaran151: Yeah, but that somehow seems a little… wrong, maybe

14:33 From a functional point of view, I'm asking when the filesystem last changed.

14:34 I think I need to mull this over a bit. I've a feeling I should tie this to a time somehow.

14:34 clojurebot: multimethods are http://clojure.org/multimethods

14:34 gtrak: mul?

14:35 whatcha talking about, clojurebot?

14:35 Chousuke: "mull this" -> multi? :P

14:35 gtrak: lol

14:35 I think I need to mull this

14:35 raek: I think clojurebot has a built-in probability of randomly interpreting an irc message as directed to itself

14:35 Chousuke: yeah

14:35 pjstadig: ~mull

14:35 clojurebot: Pardon?

14:35 pjstadig: and i don't think the content of the message matters

14:35 hiredman: weavejester: seriously, an event queue, and the consumers can keep some kind of state if they wish

14:36 weavejester: Each time we think we understand Clojurebot, it because something even more inscrutable

14:38 hiredman: Hmm...

14:38 hiredman: the way it got from what weavejester said to the bit about multimethods is 3-4 (faulty) inferences

14:39 "..time.." -> something chouser said about time -> something chouser said about multimethods -> multimethods

14:41 gfredericks: ~time

14:41 clojurebot: multimethods seperate the 20% from the 80%

14:41 gfredericks: so the fact that "time" is a substring of "multimethods" is an unrelated coincidence?

14:41 hiredman: I think so

14:42 but I dunno, the inference seems be acting more generally than intended

14:42 weavejester: hiredman: It doesn't really feel like a queue. I mean, if I don't care about how many events there are when I poll.

14:43 hiredman: I don't follow how caring about "how many" has anything to do with a queue

14:43 weavejester: hiredman: I guess I could have a queue of size 1 :)

14:44 hiredman: Well, if there are zero events, I want to block until an event. If there are many events, I return immediately.

14:45 mwillhite: hey all - pretty new to clojure here…I'm trying to get some ring middleware going so that I can process params in the form of json in my compojure app

14:45 in my project.clj I have the following: [ring-middleware-format "0.1.1"]

14:45 hiredman: weavejester: seems reasonable

14:45 mwillhite: ran lein deps and it pulled down the repo

14:45 in my core.clj in the use call I have this: [ring.middleware.format-params :only [wrap-json-params]

14:46 as specified in the readme

14:46 but when I go to boot up the app I get the following error:

14:46 Caused by: java.lang.RuntimeException: No such var: clojure.core/ring.middleware.format-params

14:46 am I missing something super obvious here?

14:46 hiredman: weavejester: you have some kind of file watcher thread that generates filesystem events, that thread has a list of weak or soft references to queues, you have listeners on each side of the queues

14:46 the listeners don't have to consumer their entire queue

14:47 weavejester: mwillhite: Are you using (ns … (:use )) or just (use …)?

14:47 mwillhite: the former

14:47 weavejester: mwillhite: I'd need to see your whole ns declaration, I think...

14:48 mwillhite: sure lemme pastie it

14:48 raek: "clojure.core/ring.middleware.format-params" sounds suspicious

14:48 weavejester: hiredman: I'm still not sure why I'd want a queue when I don't care about the events themselves, just if there are any.

14:49 hiredman: It feels more like a concurrency primitive than a queue.

14:50 TimMc: There's gotta be a way to use core.logic here.

14:50 mwillhite: oh jeez, I'm an idiot…I had tacked it on after the closing paren :P

14:50 thanks! haha

14:50 hiredman: weavejester: the queue approach is more general and provides a better separation between the event generator and the consumer

14:50 weavejester: if you ever think some day you might care about the events

14:51 if you are set on using something else, maybe a cyclicbarrier?

14:52 mebaran151: a promise that unpromises itself after reference would have some utility

14:52 hiredman: :(

14:52 that's not a promise

14:52 clojurebot: Titim gan éirí ort.

14:53 hiredman: the power of a promise is the one shot nature

14:53 weavejester: hiredman: But it kinda feels like the wrong solution. I mean, I'd need to either poll and then clean the queue each time, ignore events, or set the queue size to 1 or something.

14:53 hiredman: And a queue of size 1 doesn't seem like a queue anymore.

14:54 hiredman: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html

14:56 weavejester: hiredman: That doesn't seem quite right either… It feels one step too complex - it still cares about the number.

14:56 * weavejester is being difficult :)

14:58 eggsby: so... I'm trying to dip my feet into macro lake, I have something passed to a macro, I want it passed in as a value to another function, but not evaluated... do I want to use ~ ?

14:59 ~@ will evaluate it, right?

14:59 clojurebot: @ is like the macro version of apply

15:00 Caffeine: How to keep the REPL open? I would like to start the REPL with a script (passing it a clj file in param) and keep it opened after. Can I do that???

15:00 lazybot: Caffeine: Yes, 100% for sure.

15:00 AimHere: eggsby, you probably want ` to keep code from evaulating inside a macro

15:00 Then you use ~ or @ for the bits you DO want to evaluate

15:00 eggsby: AimHere: this is inside the body of a `() statement

15:01 oh, ok

15:01 raek: eggsby: do you know enough about macros to write one without syntax-quote?

15:01 TimMc: It's not about evaluating, it's about syntax transformation!

15:01 eggsby: raek: mm, this is my first time writing a macro, and a lot of it is code borrowed from an article :3

15:02 so say I have a list inside a `() form... would I go `(my-func ~@(first my-list) ~@(rest my-list)) if I wanted it to expand to (my-func first (rest-my-list)) ?

15:02 raek: I think it best to start with thinking of macros as functions from that is applied to the source code data structures

15:03 stuartsierra: Caffeine: Pass the -r option to clojure.main

15:03 raek: eggsby: do you have a simple example of a call to your macro and what it should expand to?

15:03 eggsby: I don't really want the (rest-my-list) to be evaluated, I just want it passed in as a list minus the head

15:03 hiredman: weavejester: if you have a design with an X shaped hole, and it turns out no one has ever created an X, what does it say about the design?

15:03 stuartsierra: Check the command-line syntax by running clojure with -h

15:03 eggsby: let me make one raek

15:04 raek: eggsby: the macro code is executed at compile time. it does not know about the runtime values.

15:05 Caffeine: stuartsierra: It works! Thanks!

15:06 stuartsierra: 'welcome

15:06 raek: eggsby: one important thing that you need to know is that syntax quote is not tied to macros in any way. it's just a template language for lists, vectors and other data structures

15:07 TimMc: ,(let [x [1 2 3]] `[a b ~@x c d])

15:07 clojurebot: [sandbox/a sandbox/b 1 2 3 ...]

15:07 amalloy: i'm hopping in late here, but weavejester's problem sounds like a queue to me too

15:08 eggsby: raek: https://www.refheap.com/paste/2790

15:08 that's an inner function used by a macro

15:08 weavejester: It would have to be a queue of capacity 1

15:09 eggsby: oops, every occurance of myargs should be 'real-args'

15:09 weavejester: Which seems like not a queue

15:09 eggsby: derp... so many syntax errors there

15:10 raek: https://www.refheap.com/paste/2791 is what I meant

15:10 raek: eggsby: ok, so the macro should look at action and generate either a call to do-something or do-something else?

15:10 eggsby: yes raek

15:10 raek: ah

15:11 basically (my-macro :otheraction <a> <b> <c>) ==> (do-something-else <a> (list <b> <c>))?

15:12 eggsby: ya, but looking back maybe I should just rewrite how 'do-something-else' works...

15:12 and just use ~@ to flatten the remainder of the args, then have do-something-else use & to splat

15:13 cause just going '(some-call ~@(real-args)) results in (some-call my real args) expanded, right?

15:13 raek: do you want do-something-else to take <b> and <c> as separate args?

15:13 eggsby: ya basically

15:13 Raynes: Refheap is getting lots of paste love lately.

15:13 raek: ok, let's wait with the implementation details a bit

15:14 eggsby: but I think I should just manage that in the implementation of do-something and do-something-else, right raek ?

15:14 ok

15:14 raek: I just want to understand what the macro should to first :-)

15:14 gtrak: Raynes: mmm paste love

15:14 eggsby: raek: basically I have some expression that I want to pass to a function to conditionally evaluate

15:15 raek: eggsby: a macro can rewrite an expression into another one. is (my-macro :otheraction <a> <b> <c>) ==> (do-something-else <a> <b> <c>) fine?

15:15 so this will "compile away" the conditional that checks for :otheraction

15:15 eggsby: right

15:16 muhoo: i love it. an exception in projectname.views.something/eval24214

15:16 raek: the defmacro form could look like this then: (defmacro my-macro [action & args] ...)

15:17 action will be a keyword and args will be a sequence of code expressions

15:17 amalloy: eggsby: you know this macro can only recognize :some-action if you pass it as a compile-time literal, right? you can't do (let [action (if foo :some-action :other-action)] (my-macro action a b c))

15:18 raek: if the call looks like (my-macro :someaction (+ 1 2)), action will be bound to :someaction and args to '((+ 1 2)), and not '(3)

15:19 (defmacro my-macro [action & args] (case action :someaction ... :otheraction ...))

15:19 weavejester: A promise in an atom might be the best solution

15:19 raek: the ...s should return data that looks like (do-something <arguments-here...>) or (do-something-else <arguments-here...>)

15:20 hiredman: weavejester: :(

15:20 raek: so let's build some lists and symbols

15:20 weavejester: hiredman: I don't think there's a way to use a LinkedBlockingQueue to do what I want

15:20 eggsby: hm

15:20 hiredman: weavejester: why don you just create a singe element array and lock it

15:20 weavejester: hiredman: If I poll, I can get the head of the queue

15:21 hiredman: How would that be different from an atom with a single value?

15:21 mebaran1`: weavejester: you have two elements of state anyway, so it seems like you would need two concurrency primitives

15:21 raek: (defmacro my-macro [action & args] (case :someaction (cons 'do-something args) :otheraction (cons 'do-something-else args)))

15:21 mebaran1`: whether the atom has been read and whether the filesystem has changed

15:22 eggsby: cons... hm

15:22 hiredman: weavejester: I don't know, a promise in an atom is just so disgusting

15:22 weavejester: hiredman: I know… :(

15:22 raek: now, instead of building lists like (cons 'foo (cons x (list 'bar 'baz))), we can use `(foo ~x bar baz)

15:22 &'`(foo ~x bar baz)

15:22 lazybot: java.lang.ClassNotFoundException: clojure.core

15:23 TimMc: Yeah, lazybot is down for the count.

15:23 raek: that is actually expanded to this by the reader: (seq (concat (list 'foo) (list x) (list 'bar) (list 'baz)))

15:24 amalloy: huh

15:24 eggsby: what in the

15:24 * eggsby studies that

15:24 eggsby: hm

15:25 weavejester: hiredman: Well, I don't know. A promise is for a value we don't yet know, like… when's the next file going to be changed?

15:25 raek: if we instead write `(foo ~@x bar baz) then we would get this: (seq (concat (list 'foo) x (list 'bar) (list 'baz)))

15:25 weavejester: hiredman: So ideally you'd want to tie it to a time...

15:26 eggsby: hmm

15:26 S11001001: ,'`(foo ~@x bar baz)

15:26 clojurebot: (clojure.core/seq (clojure.core/concat (clojure.core/list (quote sandbox/foo)) x (clojure.core/list (quote sandbox/bar)) (clojure.core/list (quote sandbox/baz))))

15:27 weavejester: hiredman: And an atom ties a value to an identity at a certain time.

15:27 hiredman: I think I may jsut stick my fingers in my ears and say "queue queue queue queue ..."

15:27 weavejester: hiredman: But the queue would only have one element! That's not really a queue, right?

15:27 hiredman: weavejester: why would it only have one element?

15:27 amalloy: i put a delay in an atom recently. not as weird as a promise, but still feels a little weird

15:28 raek: eggsby: the macro can the be written like: (defmacro my-macro [action & args] (case :someaction `(do-something ~@args) :otheraction `(do-something-else ~@args)))

15:28 hiredman: weavejester: your current consumer may only care about 1 element

15:28 eggsby: raek: what if x was a primitive and couldn't be "flattened" like that

15:28 weavejester: hiredman: Because I want to trigger a refresh when any amount of files change

15:29 TimMc: ,(let [x 5] `[a b ~@x c d])

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

15:29 eggsby: so if x were (2 3) `(1 ~x 4) would be (1 (2 3) 4) and `(1 ~@x 4) would be (1 2 3 4), right?

15:29 pjstadig: don't do that

15:29 TimMc: eggsby: Just what you'd expect.

15:29 raek: eggsby: like 123? then the code would expand to (seq (concat (list 'foo) 123 (list 'bar) (list 'baz))) and you would get an error when that is evaluated

15:29 weavejester: hiredman: But there's no atomic operation to block and consume all of a blockingqueue

15:29 eggsby: ah, okay raek

15:29 that helps a lot, thanks

15:29 raek: the macro constructs new code that is sent back to the compiler

15:29 weavejester: hiredman: I can poll it to get the head

15:29 eggsby: so what is the difference between ' and ` ?

15:30 ieure: Is there a Clojure/Java equivalent to Python's cmd library? http://docs.python.org/library/cmd.html

15:30 It's a REPL building framework.

15:30 raek: eggsby: with ' you can't have "holes" like ~ and ~@

15:30 also, ` makes symbols namespace safe

15:30 eggsby: ah, I see

15:30 weavejester: hiredman: But I don't see how I can use a blockingqueue to do this

15:30 TimMc: raek: Don't forget gensyms.

15:31 hiredman: weavejester: https://developer.apple.com/library/mac/#documentation/Darwin/Conceptual/FSEvents_ProgGuide/KernelQueues/KernelQueues.html http://linux.die.net/man/7/inotify http://c2.com/cgi/wiki?EventQueue

15:32 you pull a message from the queue, check it meets some set of conditions, and if it does you trigger some action, then go back to polling

15:33 TimMc: and throw timeouts into the queue as well?

15:33 hiredman: TimMc: most queues let you poll with a timeout

15:33 lbq definitely does, and so does every messagebus I know of

15:34 weavejester: hiredman: That's a point...

15:35 hiredman: weavejester: you can even push the state management even farther down, by making it all internal to the refresh function, so refreshing is always throttled no matter how you call it

15:35 throttled to 60hz or something :)

15:37 refresh can be a scheduled function that checks a "re-render" flag

15:37 so refresh runs every S seconds and just looks at an atom to see what needs to be redrawn

15:38 weavejester: Hm...

15:39 Because the "refresh" is a response returned, I can't do that exactly

15:44 Hm, also, a queue wouldn't work because there could be multiple consumers.

15:47 TimMc: weavejester: To recap, you need to take an action iff at least one event has occurred since the last time you took action, but only once x milliseconds have passed since the first such event?

15:48 hiredman: weavejester: that does not preclude a queue

15:48 TimMc: (with the delay intended to allow grouping)

15:48 hiredman: you each consumer gets a queue

15:49 weavejester: TimMc: I basically have a route in my web app that tells a javascript function whether or not to refresh the current page.

15:49 So the javascript sends an XHR to the route

15:50 If no files are changed it waits up until a timeout before returning false

15:50 If any files are changed it returns true

15:51 TimMc: I think you can separate the blocking -- "taking action" could mean signaling all waiters on an object.

15:52 weavejester: Right...

15:53 hiredman: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#wait%28long%29

15:53 weavejester: But because each consumer is temporary, I can't assign them a queue.

15:53 TimMc: weavejester: False positives are bad?

15:53 hiredman: http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#notifyAll%28%29

15:53 weavejester: hiredman: Yeah, I was thinking about that...

15:54 hiredman: But is keeping an lock object any better than a promise?

15:54 TimMc: Well, I don't want to change 10 files, and then have it refresh 10 times

15:54 hiredman: weavejester: yes

15:55 TimMc: weavejester: So each waiter needs to have its own notion of a timeout, but they all rely on the same event stream.

15:55 weavejester: TimMc: Yes...

15:56 hiredman: "spurious wakeup" ugh

15:57 weavejester: This is making me feel dumb. It feels like such an easy problem :)

15:58 TimMc: I'm having trouble with the idea of uses queues here. Queue read timeouts are a different *kind* of timeout than what you need.

15:58 hiredman: you need broadcast queues, which java.lang.concurrent doesn't have, but you can build them

15:59 weavejester: I think I need a broadcast something, but I don't see why it should be a queue, when I don't care about the items being queued.

16:00 hiredman: right, which is why you want a broadcast queue that goes away when no one is listening

16:00 weavejester: A promise seems like the right way of delivering a single value to multiple threads when it's ready.

16:00 I mean, that's what it's for, right?

16:01 hiredman: for a one shot value

16:01 weavejester: Yes, but you could have a function returning a promise

16:03 Like… (next-modification-date dirs)

16:03 Which would return a promise of the next modified date in the directories

16:03 I guess it would be more like (next-modified dirs timestamp)

16:05 I guess I'll think about it.

16:08 TimMc: weavejester: When a waiter comes in, it creates an atom and registers a closure over it with the notification service, then sleeps for 100 ms. Each time a file event happens, all the closures are called with the event info. In this case, each closure sets its atom's state to true. When the timeout is over, the waiter returns the atom's value.

16:08 (Oh, and unregisters its atom.)

16:12 weavejester: Alternatively, the notification service maintains a file event count. Client-side code keeps this as an opaque data value and sends it along with the XHR, getting a replacement value back each time -- along with whether to refresh as calculated by (!= old new).

16:12 Raynes: TimMc: Man, I thought you were talking about a restaurant for a moment there.

16:13 TimMc: This approach does not rely on any queue, and each waiter simply sets a timeout and does that simple calculation when the timer fires.

16:14 Raynes: I'm not? :-(

16:14 Raynes: I see what you did there./

16:19 TimMc: Raynes: What I did == killed the channel?

16:19 gtrak: is there a = that treats nested seqs/vectors within a map the same?

16:19 Raynes: TimMc: Yes.

16:19 gtrak: like... I don't want it to fail if the thing's a vector instead of a seq

16:20 TimMc: &(= {:a [1]} {:a (seq [1])})

16:20 lazybot: ⇒ true

16:21 TimMc: gtrak: vectors and seqs are in the same equality partition

16:21 gtrak: ah, I'm just doing something wrong :-) thanks

16:21 that's good to know anyway

16:21 TimMc: gtrak: Last table: http://www.brainonfire.net/files/seqs-and-colls/main.html

16:22 gtrak: neato

16:22 TimMc: Technically it only shows a list vs. a vector, but whatevs. :-P

16:22 gtrak: what i did was I used defn vs def accidentally, so it tried to equate a map and a function xD

16:22 but i've never seen a defn without an arglist, why would that work?

16:23 ,(defn parsed {:graphs '("graph1" "graph2") :endpoint "http://url" :all? true})

16:23 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

16:23 gtrak: &(defn parsed {:graphs '("graph1" "graph2") :endpoint "http://url" :all? true})

16:23 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

16:23 gtrak: &(fn {:graphs '("graph1" "graph2") :endpoint "http://url" :all? true})

16:23 lazybot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentArrayMap

16:23 gtrak: hmm..

16:52 devn: Raynes: do you know off the top of your head, is it possible to capture *out* from (sandbox (safe-read "(println 1)"))? I'm using (with-out-str and I'm just getting back empty string. How would I capture *out* here?

16:54 ibdknox: devn: you can supply a set of bindings to the sandbox, you need to bind *out* to your own thing and then read from that

16:54 Licenser: devn not sure how it is in raynes sandbox but for clj-sandbox stuff like *out* and stuff were bound on the creation of a sandbox

16:57 devn: ibdknox: im not seeing where

16:58 muhoo: it is so funny how much the vc/tech business reminds me of the music business

16:58 devn: Licenser: yeah im not sure that happens anymore

16:58 dgrnbrg: what's the easiest way to print a double w/ 2 digits of decimal places?

16:58 muhoo: you develop an indie following, then you get signed by a major

16:58 dgrnbrg: or just to convert a double to a string w/ 2 digits of decimal places?

16:59 technomancy: ,(format "%0.2f" (/ 2 3))

16:59 clojurebot: #<MissingFormatWidthException java.util.MissingFormatWidthException: 0.2f>

16:59 technomancy: ,(format "%.2f" (/ 2 3))

16:59 clojurebot: #<IllegalFormatConversionException java.util.IllegalFormatConversionException: f != clojure.lang.Ratio>

16:59 Raynes: devn: lazybot has examples of rebinding *out*.

16:59 technomancy: ,(format "%.2f" (float (/ 2 3))) ; FINE CLOJUREBOT

16:59 clojurebot: "0.67"

16:59 Raynes: What ibdknox said is spot on.

17:00 devn: Raynes: thanks, and thanks ibdknox

17:00 dgrnbrg: technomancy: thanks

17:00 devn: and thanks Licenser for starting the whole thing :)

17:00 Raynes: devn: Also, I showed an example in my talk. Did you not pay attention? :(!

17:00 Licenser: ^^

17:00 Raynes: I'm hurt, devn.

17:00 devn: Raynes: lol. i have that one coming.

17:00 i was out until 4am the night before and walked in near the end :X

17:01 Licenser: Raynes if there's one thing you should have learned ins school it's: students never listen to what the teacher sais

17:01 Raynes: I slept through most of the conference, so totally understandable.

17:01 muhoo: ok, so snoir send-request blows up with clojure.lang.Var$Unbound when there is a noir.session/flash-get in the page

17:02 apparently *noir-flash* doesn't exist when send-request is used

17:02 devn: Raynes: wicked. thanks.

17:05 TimMc: &(defn oops {:some :map})

17:05 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

17:06 Raynes: muhoo: Those things are only bound inside of a request.

17:06 TimMc: Urr... right. ANyway, if you then do (oops), you get a NPE

17:06 devn: Raynes: seems like some of the stuff in lazybot could maybe be brought over to clojail? maybe?

17:06 Raynes: devn: Perhaps.

17:07 devn: seems like someone like me could do that...

17:07 ;)

17:07 Raynes: :p

17:07 devn: what does box? do?

17:07 (skimming the lazybot clojure.clj plugin)

17:08 Raynes: devn: You can run lazybot and let his eval plugin work without a sandbox. It is useful in private company channels and stuff where you know your employees and coworkers aren't going to delete your machine.

17:08 Or if you run it on a work machine or something.

17:08 muhoo: so i'm confused then how to mock/test a noir app. i figured send-request would do it, but i guess not.

17:08 Raynes: I added it because we do at Geni.

17:08 devn: Raynes: gotcha

17:08 Raynes: devn: It probably isn't particularly elegant. I sometimes add things on the fly without really thinking them through.

17:08 It's a character flaw.

17:09 muhoo: There is a way to mock all of those things, but I sure don't remember what it is.

17:09 ibdknox:

17:09 Licenser: Raynes you trust your coworkers enough for that?

17:09 Raynes: ^

17:09 Licenser: Sure, it runs on a company server.

17:09 Not my problem if they delete stuff on that. :p

17:10 Licenser: wow I'd not trust any of my colegues furthen then I can throw them - and many of them are rather heavy

17:10 hah

17:10 TimMc: "Raynes' bot deleted some stuff on the server!"

17:10 devn: It could be a lot of fun. send messages to raynes by popping up swing guis

17:10 Raynes: Haha

17:11 TimMc: "Including its own logs, mysteriously!"

17:11 devn: i actually ran everything from #clojure *without* safe-read the first time

17:11 and no issues

17:11 technomancy: now that you said that though...

17:11 Raynes: TimMc: You should send me a lazybot pull request fixing the escaping problem in the logs.

17:11 devn: technomancy: lol

17:11 TimMc: devn: I remember when you found out about *read-eval*...

17:12 Raynes: Man, watching Stuart Sierra's talk was the scariest thing about the Conj.

17:12 TimMc: Raynes: Why so concerned about it suddenly?

17:12 Raynes: We all thought he was going to pretty much cover the topic of my talk. It turned out to be an excellent primer for my talk though.

17:12 He talked about *read-eval* and stuff which is highly relevant to how clojail works.

17:13 muhoo: aha! (with-noir (send-request "/")) ftw

17:13 Raynes: TimMc: because you're malevolent and I'd rather have you on my side.

17:13 * TimMc introduces subtle bug into escaping code

17:14 TimMc: Also, OMG, you haven't <b>fixed</b> that yet?

17:16 I don't know where that code even lives. Not up for archaeology at the moment.

17:16 Raynes: TimMc: src/lazybot/plugins/logger.clj

17:17 TimMc: But it logs to text file, yeah? Not the place to escape stuff, really.

17:17 At least, not the place for HTML-encoding.

17:18 What's broken is the web server, perhaps the JS.

17:19 Raynes: TimMc: Yeah, but it'd be cool if lazybot served the text files himself. So do that.

17:20 TimMc: OK, but I'll make it only respond to SPARQL queries.

17:21 Raynes: $('#log').html(lines.join("\n")); is the culprit. Map over lines with an html-encoding function, then join on "<br>".

17:22 I also shudder to think what kind of path traversal exploits you might have in the server.

17:26 Raynes: Or hell, you may be able to just dump the contents in via .text() and use a CSS style to force line breaks to be respected.

17:28 eggsby: hey raek with your help I was able to get my macro working, thanks!

17:29 raek: eggsby: np :)

17:32 muhoo: now, if only there were a way to maintain a cookie store through several (with-noir (send-request)) requests, hmm

17:32 putting several send-requests inside one (with-noir) does not cut the mustard

17:58 fil512: how can I turn a string into a BufferedInputStream?

17:58 when I try (io/input-stream string)

17:59 it interprets my string as a filename

17:59 weavejester: ByteArrayInputStream

17:59 fil512: what would the syntax be?

17:59 S11001001: fil512: there's no syntax, it's just normal java calls

17:59 fil512: I've never made a normal java call before

18:00 in clojure

18:00 S11001001: http://clojure.org/java_interop

18:00 weavejester: fil512: (ByteArrayInputStream. (.getBytes s))

18:00 So (.getBytes s) is equivalent to the java s.getBytes()

18:00 And (ByteArrayInputStream. foo) is equivalent to: new ByteArrayInputStream(foo)

18:03 nDuff: What's the CCW equivalent to paredit's ctrl+right, ie. [(foo|) bar] => [(foo| bar)]

18:05 fil512: weavejester: thank you

18:09 is there a quick way to turn my map keys to keywords?

18:09 from strings

18:11 raek: fil512: clojure.walk/stringify-keys

18:14 devn: Raynes: hehe -- just found out why all the stuff in my DB started to magically get "I'm a string: ..." in them:

18:14 Raynes: http://clojure-log.n01se.net/date/2008-11-09.html#16:34

18:15 Raynes: Hahahaha

18:15 devn: lol

18:16 Raynes: other question for you: are these sandbox local? WARNING: next already refers to: #'clojure.core/next in namespace: sandbox5320, being replaced by: #'clojure.zip/next

18:16 espeed: is there a way to define a default value to return if a record doesn't contain a key?

18:16 devn: I'm allowing def, those won't persist will they?

18:16 hiredman: devn: that's the result of someone doing (use 'clojure.zip)

18:16 TimMc: espeed: ##(doc get)

18:16 lazybot: ⇒ "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

18:17 devn: hiredman: any idea what would cause this one? WARNING: map already refers to: #'clojure.core/map in namespace: sandbox5320, being replaced by: #'clojure/map

18:17 hiredman: that's just all alone

18:17 TimMc: espeed: And records probably support that syntax directly, too.

18:17 hiredman: devn: that is just weird

18:17 devn: happened somewhere around 10-22

18:17 (2008)

18:18 hiredman: (do (in-ns 'clojure) (def map 1) (in-ns 'sandbox) (use 'clojure))

18:18 oh

18:18 2008 would have been around the time the clojure ns became clojure.core

18:18 maybe late 2008

18:20 technomancy: late 2008; the scars were still fresh when I joined.

18:22 espeed: TimMc: thanks. I am for something more like __getattr__, which is a function that's called if an object doesn't contain an attribute; so that the default value doesn't have to be explicitly passed to "get"

18:22 (__getattr__ in Python)

18:22 devn: hiredman: so, still -- how did that happen?

18:22 hiredman: do you see what did it here? http://clojure-log.n01se.net/date/2008-10-22.html

18:24 hiredman: devn: http://clojure-log.n01se.net/date/2008-10-22.html#00:59

18:24 if sometime ealier someone had done (in-ns 'clojure) (defn map ...) or similar

18:25 devn: hiredman: bingo. thanks

18:28 yoklov: espeed: if you implement IFn, and use the record as a function (as you also often do with maps and such), you can handle it the way you would like. there might be another way, but I'm not aware of it

18:40 espeed: yoklov: thanks

18:40 * nDuff stares at nrepl's code a bit, trying to determine the Right Way to control Thread.contextClassLoader without replacing nrepl.middleware.interruptible-eval

18:41 TimMc: espeed: "implement IFn" is a minor nightmare, by the way

18:42 nDuff: espeed: ...oh, hey, you're the one porting the graph library? Think I've seen a few of your questions over on StackOverflow

18:42 espeed: nDuff: yes, as a Clojure learning exercise

18:42 nDuff: espeed: ...very much IMHO, but trying to Python idioms over to a non-Pythonic language seems a bit silly.

18:42 yoklov: TimMc: why is implement IFn a nightmare? You don't have to implement all the arities

18:42 nDuff: s/trying to/trying to port/

18:43 espeed: nDuff: part of this process if figuring out the "Clojure-way" of doing things

18:43 TimMc: yoklov: No?

18:43 espeed: *is

18:44 yoklov: TimMc: at least, you don't in ClojureScript, though maybe it's different because in cljs IFn is a protocol and not a java interface?

18:45 hiredman: (for [i (range 20) :when (not= arity-I-care-about i)] `(invoke ~(vec (repeat i '_)) (throw (IllegalSomethingOrOther.))))

18:45 then you just copy and paste the output of that for into your deftype

18:47 https://github.com/hiredman/clojure/blob/41df324e8e6699af82d6d3d2ccaae4ae840904ad/src/jvm/clojure/lang/RIC.java#L1864

18:50 amalloy: don't forget the this-arg

18:50 hiredman: sure

18:50 that

18:54 devn: Raynes: i conj'd 'defmethod onto secure-tester-without-def, but it still seems to eval it

18:57 Raynes: maybe not

19:27 eggsby: hmm, say I have a sequence of functions, how can I expand those out into individual function calls?

19:28 like (list even? (partial = 2)) etc and I have some value I want to apply to every function

19:28 more specifically I want to say (and (pred1 data) (pred2 data) (pred3 data)) etc

19:29 so it'd be expanded to something like (and (even? 2) (= 2 2))

19:30 amalloy: (every? #(% data) fns)

19:31 technomancy: couldn't you use juxt for that?

19:32 (apply every? ((juxt f1 f2 f3) x))

19:33 that's wrong, but it uses juxt, so it's better

19:33 raek: :)

19:33 eggsby: grr this stupid problem won't bend to my will

19:34 every works amalloy thanks, I'll just have to make stuff play nice with it

19:35 amalloy: technomancy: laziness, though

19:36 i think a version with juxt that works (laziness aside) is like (every? identity ((apply juxt fs) x))

19:36 technomancy: every? true?

19:39 raek: juxt is better - even when it's wrong

19:39 that should be the motto of the juxt fan club

19:40 amalloy: technomancy: i'm pretty sure we want identity here, unless you're insisting on every function returning a boolean

19:41 technomancy: guess it depends on the domain

19:41 clojurebot: excusez-moi

20:46 gfredericks: I was shown speclj for the first time today and cannot figure out why the (with) macro creates a derefable

20:49 nDuff: Is ccw.clojure available as part of any published Maven repository?

21:25 dnolen`: a page describing how to extend core.logic http://github.com/clojure/core.logic/wiki/Extending-core.logic-(Datomic-example)

23:22 ForSpareParts: Is there any way to examine a clojure function from clojure? Like as a list of function calls, maybe?

23:27 xeqi: ForSpareParts: are you looking for ##(doc source) or something like https://github.com/frenchy64/analyze

23:27 lazybot: java.lang.RuntimeException: Unable to resolve var: source in this context

23:27 xeqi: &(doc clojure.repl/source)

23:27 lazybot: ⇒ "Macro ([n]); Prints the source code for the given symbol, if it can find it. This requires that the symbol resolve to a Var defined in a namespace for which the .clj is in the classpath. Example: (source filter)"

23:28 ForSpareParts: Not sure which would do it. I'm thinking about unit testing and regression -- it would be useful to be able to list all the functions called by a given function.

23:29 Unless there's a much better way of doing that sort of thing that I'm just missing...?

23:29 dnolen`: ForSpareParts: it's possible but you would need to adapt an analyzer like the one that ships with ClojureScript

23:30 ForSpareParts: hm. Does vanilla Clojure not come with one?

23:31 brehaut: not currently

23:31 ForSpareParts: Interesting.

23:32 Am I missing a better approach to this problem? I was thinking about a Java implementation, but it turned into a big OOP mess in my head.

23:32 brehaut: clojurescript is sort of a proof of concept for clojure in clojure. its also clojure implemented with 3 or so years hindsight, so its got tricks that jvm clojure does not

23:34 dnolen`: ForSpareParts: I believe Clojure does have an analyzer but I don't think it's very easy to use.

23:34 ForSpareParts: just use the one in ClojureScript, analyzer is like <500 lines of code or something.

23:34 brehaut: ambrosebs has a port of it to clojure doesnt he?

23:35 ForSpareParts: Yeah, I found something about the Clojure analyzer on dev.clojure.org that links to the Frenchy64 project that xeqi linked me to.

23:39 zakwilson: I can't find the new comment reader syntax with google. What is it?

23:40 dnolen`: zakwilson: new?

23:40 zakwilson: dnolen`: there's something new in 1.4, as I recall.

23:41 dnolen`: zakwilson: tagged literals

23:44 zakwilson: dnolen`: found it in the reader source: #_

23:45 dnolen`: zakwilson: that's not new

23:46 zakwilson: dnolen`: I'll take your word for that. I only learned about it recently and I made a mental note of it being new.

Logging service provided by n01se.net