#clojure log - Oct 05 2010

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

1:51 nathanmarz: hey guys, is there a standard way to mark a clojure function as deprecated?

2:03 scottj: both clojure and contrib do it with a map after doctring {:deprecated "version number"}

2:05 I don't know if that's actually used by clojure or any tools

2:22 amalloy: scottj: it's used by the API ref, anyway

2:38 brehaut: hello

2:40 amalloy: hi brehaut

3:05 ossareh: hey, I'm running lein uberjar, and it's compiling my various clj files - however there is an ns that only becomes available at runtime and as a result the compiler complains that it cannot find the ns. Is this where you're expected to use ' ?

3:06 i.e. 'runtime-ns/var

3:06 ?

3:53 amalloy: i've been poking around at rosettacode tonight; does anyone see an improvement to http://rosettacode.org/wiki/Probabilistic_choice#Clojure? i couldn't find a good way to do either (to-cdf) or (choose)

3:57 neotyk: Good morning

3:57 amalloy: morning neotyk

3:59 neotyk: Is there something sequence library that would allow me not to write it like here: http://gist.github.com/611192 ?

4:00 amalloy: neotyk: i think you can use destructuring for this

4:01 neotyk: amalloy: where would it help?

4:02 amalloy: neotyk: the :or keyword does some magic

4:02 i don't use it often, lemme play around with it to find out the right syntax

4:02 neotyk: amalloy: :or is used when there is no valye provided, right?

4:03 amalloy: neotyk: sorry, i only sorta scanned your code. sounds like i didn't scan it well enough :)

4:03 what is it you're trying to do?

4:07 neotyk: map some properties

4:07 say property :a tp :c

4:07 s/tp/to/

4:07 sexpbot: <neotyk> say property :a to :c

4:09 amalloy: yes, it's clear that you want to map some properties, but not clear what that means :P

4:09 i guess i'll just run your code and see what it does

4:11 neotyk: you have props with "old.prop.name" and want to have it's value to "new.prop.name"

4:11 and make sure old code works

4:22 LauJensen: Morning all - I didn't know that America had Giraffes: http://i.imgur.com/nr2Fc.jpg

4:23 hiredman: I have three

4:23 LauJensen: :)

4:24 abrenk: three of those!? :-)

5:20 esj: that one is three in one

5:32 carkh: (.toString ^java.net.URI (-> state :request :uri)) i get reflection warning there in 1.2

5:32 is it the way it should be ?

5:32 if i go (let [^java.net.URI uri (-> state :request :uri)] ..) no reflection warning

5:49 raek: carkh: I think the metadata ends up on the (-> state :request :uri) list, which is removed by that macro

5:50 I don't know if you can typehint arbitrary expressions

5:50 carkh: it used to be valid in 1.1

5:50 ohwell i'll make do

5:50 raek: oh..

5:51 carkh: actually iirc you could even put type hints inside the -> form

5:52 i'll wait for america to wake up and see if i can get hold of a maintainer =P

5:53 raek: :)

6:53 neotyk: at the end of this month there is a clojure conj, and there is 3rd clojure bday party

6:53 is there any milestone that is Clojure birth day?

8:33 bartj: Please advise if this scenario requires agents or can be done with something better ?

8:33 I have 1M records and need to save them to a database. My idea is to break these into partitions of 500 each.

8:33 And call a function "save-database" on each partition of size 500.

8:33 The thing is I would like to use agents - but, there is no shared/mutable state

8:33 in the above process. The reason I would like to use agents is to spawn

8:33 threads for each save operation; so that they can happen parallely.

8:35 chouser: if they're all writing to the same database, can they really happen in parallel anyway?

8:35 cemerick: Indeed, that's going to IO-bound primarily.

8:36 Though, there's no point in thinking about "partitioning". (dorun (pmap save-database 1-meeelion-records)) should do it.

8:36 Sort of a waste of 1M perfectly good futures. :-P

8:38 chouser: heh

8:41 bartj: chouser, yeah, you are right

8:42 I mean these are *new* records, so the database is not locking atleast the *record-level*

8:43 *atleast at the

8:43 chouser: but is probably locking the table for append, right?

8:43 cemerick: jeez, I'd hope not

8:44 bartj: er, this is not a classic mySQL database

8:44 it's CouchDB

8:45 cemerick: bartj: in that case, your time is going to be dominated by writes on the couchdb side due to its durability guarantee. You want to use its bulk_docs api. Clutch supports it directly, FWIW. http://github.com/ashafa/clutch

8:46 bartj: oh yes, I am using the bulk_docs feature

8:46 cemerick: that explains your desire to partition the records :-)

8:46 bartj: though, it is actually the bulkCreateDocuments from the jcouchdb lib

8:47 ok, re: the question -> there is no state here

8:47 cemerick: sure, either way

8:48 bartj: and I want to start multiple threads...

8:48 so is agents the only way to go ?

8:48 cemerick: Threads are very low-level, and there's generally no reason to touch them in Clojure.

8:48 chouser: you want one thread per batch?

8:48 bartj: my train of thought is that:

8:49 I plan on calling an agent

8:49 chouser, yes

8:49 cemerick, er, I meant agents

8:49 dnolen: bartj: you might find this interesting

8:50 not sure if agents are necessary if you just need to load 1M records as fast as possible, batching should do the trick

8:50 It didn't seem like you could get CouchDB to write much faster to disk, but if you find out different, I'd like to know

8:50 bartj: http://dosync.posterous.com/stm-couchdb-and-pushing-5500-documentssecond

8:52 bartj: dnolen, yes, I am not sure if agents are necessary; that is the only way I know to spawn threads :)

8:53 cemerick: dnolen: IMO, not sure why refs are necessary there. An atom or a simple LinkedBlockingQueue would do the job. *shrug*

8:53 dnolen: bartj: I able to load about 1M tiny documents in about 3 minutes.

8:53 cemerick: yeah, I realized that later.

8:53 cemerick: bartj: agents don't spawn threads

8:53 dnolen: just checking ;-)

8:53 chouser: cemerick: I was looking at that. he's using the insert-queue to create the batches, not really as a work queue.

8:54 bartj: cemerick, yes you are right

8:54 dnolen: cemerick: actually atom could work right, I need to check the count?

8:54 chouser: cemerick: sometimes agents spawn threads

8:54 dnolen: s/could/couldn't

8:54 bartj: cemerick, but, at the end of the day you have to "send" something to an agent

8:55 cemerick: chouser: same-same as .size() & .drain() on LBQ, no?

8:55 bartj: cemerick, which would definitely spawn a thread.

8:55 chouser: dnolen: you'd use the return value of 'swap!' to see if you're the one that took it up to 50

8:55 bartj: , (doc send-off)

8:55 clojurebot: "([a f & args]); Dispatch a potentially blocking action to an agent. Returns the agent immediately. Subsequently, in a separate thread, the state of the agent will be set to the value of: (apply action-fn state-of-agent args)"

8:55 chouser: cemerick: maybe, but not sure that's easier.

8:55 cemerick: bartj: send-* *occupies* a thread, but doesn't necessarily allocate one. It's a critical distinction.

8:55 dnolen: chouser: but in the time to get to a flush couldn't another item have been added?

8:56 chouser: dnolen: oh, good point. it can be done, but with current atom api it'd be messy

8:56 dnolen: chouser: I'm actually learning Clojure! :D

8:56 chouser: there's been talk of a 'swap!' fn that would return old and new values of the atom

8:57 dnolen: of course you are! that's some pretty clean code there, doing something that's actually useful.

8:57 bartj: cemerick, ok...then my question would be when does it get allocated ?

8:57 chouser: dnolen: anyway, if you had a swap+!, you could do something like...

8:58 dnolen: chouser: i've seen you mention something like this before on channel

8:58 cemerick: bartj: when using send-off, when there's no available threads in the associated threadpool (up to some limit, perhaps). But seriously, you shouldn't even think about it.

8:58 There's no way to reason about when send-off, future, etc actually allocate threads.

8:59 bartj: cemerick, thank you...but, my question is not related to the timing of "allocating a thread"

9:00 my question is primarily: " do agents create a thread to change the state?"

9:00 AWizzArd: cemerick: iirc in earlier Clojure versions future every time created a new thread. Now it uses the same thread pool that agents use.

9:01 chouser: (let [[oldq] (swap+! insert-queue #(if (== 50 (count %)) [new-item] (conj % new-item)))] (when (== 50 (count oldq)) (send-off ...)))

9:01 AWizzArd: And send-off tries to take an agent out of the thread pool, and if none is available it creates a new thread.

9:01 chouser: bartj: you are right to notice you don't care about the agent's state and therefore have doubts as to whether they're the right mechanism

9:01 AWizzArd: Do I remember this correctly?

9:02 cemerick: AWizzArd: nope, you have it right

9:02 chouser: bartj: consider 'future' in such circumstances

9:03 bartj: or an Executor thread pool of your own

9:04 cemerick: so I now have maven scratch projects for launching clojure 1.0, 1.1, 1.2 and master REPLs, all with my most happily customized options.

9:04 cemerick: 1.0, even! :-)

9:04 bartj: thanks everyone!

9:05 everytime I come here, it re-inforces my lack of knowledge :)

9:05 chouser: they share a command-line history, optionally use pprint when available (from contrib for early versions, clojure.pprint later), prompt coloring, etc.

9:05 cemerick: chouser: nicely enough, the next rev of clojure-maven-plugin will add a <packaging>clojure</packaging> option, which will eliminate the need to bind the goals to build phases.

9:06 chouser: cemerick: I haven't yet confirmed that a change in my own clojure proj will be picked up by the master repl, but based on the behavior I saw last night I think it's likely

9:06 cemerick: chouser: sounds like you have a good basis for packaging some clojure maven archetypes

9:06 chouser: I have no idea what that means. :-D

9:07 cemerick: They're new project templates -- thousands of them out there for various languages, frameworks, types of applications, etc.

9:07 chouser: I would like to learn at some point how to have maven not spend several seconds deciding it doesn't need to compile and .java files, etc.

9:08 cemerick: having them in central would allow one to do something like `mvn archetype:create clojure-1.2` and get a baseline pom and project structure spit out to disk.

9:08 chouser: as for clojure and contrib building compilcations, I think the instructions in contrib that rhickey and I have been following may be unnecessarily complex.

9:08 cemerick: I'd definitely agree on that count.

9:09 chouser: a lot of my logic is outside the pom, since I still mostly hurt myself when I try to change that.

9:09 the distance between a maven feature's docs, it's source, and the xml to interact with it is so large as to cause vertigo

9:10 cemerick: aside from my work on the clojure-maven-plugin, I don't think I've ever looked at a plugin's source

9:10 chouser: well, when the docs fail you...

9:11 cemerick: But I'd heartily recommend using an editor with good tag completion + popup documentation for the same.

9:11 chouser: cemerick: as soon as I find one of those with correct key bindings, I'll be all over it. :-)

9:12 cemerick: Ouch. :-(

9:12 chouser: but seriously, I wanted to get clojure:repl to run some clojure code before going to the prompt

9:13 or alternatively have my own phase/targe/whatever that ran my code instead of clojure-maven-plugin's idea of a repl

9:13 cemerick: chouser: You've no idea how your asceticism hurts you in that area :-)

9:14 chouser: I saw nothing in the plugin's rather sparse docs, though looking at it source code there were clearly options available.

9:14 cemerick: chouser: There's a <replScript> config option, that appears to be what you want.

9:14 chouser: are you saying if I had been using eclipse or something it would have prompted me with where I could instert replScript?

9:15 cemerick: Yup -- I found <replScript> by putting my cursor inside of the <configuration> element and hitting Cmd-/ (my code-completion binding)

9:15 chouser: yeah, I found replScript in the source. ...took me another few minutes to learn that it belonged inside <configuration>, inside <plugin>

9:15 same for discovering <configuration>?

9:15 cemerick: chouser: heh, yeah

9:16 chouser: sigh

9:16 cemerick: Dude, it's eclipse, welcome to 2003 ;-)

9:16 it even has vi bindings, IIRC

9:16 chouser: it's just rude

9:16 cemerick: yeah, it does sorta.

9:16 cemerick: ha

9:16 chouser: I may end up there yet

9:16 cemerick: me, eclipse, or xml?

9:17 I've give you a little demo when we're at the conj

9:19 chouser: oh, I dunno. I guess the mindset that creates things like java and maven config files -- languages that are painful unless you use a large vertical stack of software to manipulate them even though that's not inherently necessary

9:19 java the language

9:19 abrenk: chouser: building clojure-contrib with a custom clojure will be easier when stuartsierra applies my patch

9:19 rrc7cz: chouser: but then how would large companies like BEA and IBM make money selling you tools to manage the complexity they create?

9:20 chouser: cemerick: yeah, I'm hoping lpetit's demo will drive me over the edge.

9:20 rrc7cz: oh, stop pushing my buttons. :-)

9:20 rrc7cz: chouser: recognize the genius ;-)

9:21 I recently attended a presentation by some IBM fellow on their WebSphere BPM tool. He showed us Hello World and it was like 200 lines of XML. Seriously.

9:21 cemerick: rrc7cz: of course, I've never paid anyone a dime for my eclipse or netbeans toolchains

9:22 chouser: rrc7cz: but think of the flexibility!

9:22 Chousuke: :D

9:22 rrc7cz: :-D indeed. Just make sure to clear your afternoon schedule because to run their Hello World you have to boot up WebSphere itself

9:22 cemerick: I've never grokked the minimalist bent of the hacker ethos, if I may phrase it as such.

9:22 rrc7cz: cemerick: you haven't, but I bet any company running a J2EE stack has paid a bundle for their app server

9:23 cemerick: rrc7cz: well, we run tomcat *shrug*

9:23 rrc7cz: cemerick: I "got it" when I switched from PHP to J2EE due to a job change. My first reaction to the config, compile-package-deploy-boot cycle was, "are you kidding me? people actually develop like this??"

9:24 cemerick: OSS has (for better or worse) trained us all to believe that software should be gratis

9:24 rrc7cz: cemerick: for now you do :-) wait till you need JTA/distributed transactions, resource adapters, and the whole bloody lot

9:24 cemerick: rrc7cz: if your counterpoint to the JVM toolchains is PHP, you've lost me from the start

9:24 chouser: heh

9:25 cemerick: we use couchdb on the backend, I can't imagine

9:25 rrc7cz: cemerick: forget PHP the language and think about "dynamic scripting languages" You could replace it with Ruby, Python, whatever. The development style is the same

9:26 what I was trying to say was: change this line of code and refresh the page. Bam, it's done. I love it

9:26 cemerick: Such things are fundamentally targeted at a category of problems that I'm entirely uninterested in. *shrug*

9:27 Eh, jetty and tomcat do the same dance. And a remote REPL beats 'em all. :-)

9:27 chouser: but that's because of clojure

9:27 rrc7cz: cemerick: agree on the REPL, that's why I'm in love with clj/scala/etc.

9:28 cemerick: chouser: Indeed, though JRebel is some serious magic too.

9:28 or whatever they're calling it these days

9:28 chouser: yeah, though that does still require a round of javac each time, doesn't it?

9:28 cemerick: wait for it....

9:29 chouser: if you're using any of their IDE plugins, it all happens in the background, including the "redeployment"

9:29 chouser: :-0

9:29 er

9:29 :-)

9:30 rrc7cz: but in practice the "redeployment" is of course slower than an interpreted language because you must compile + deploy. You can also run into problems blowing out the PermGen because you keep redeploying these class definitions but the old one never gets GC'd because it lives in PG

9:30 i guess my feeling is: you can _kinda_ get the same effect.. maybe 80% there

9:31 cemerick: rrc7cz: You're wrong on both points.

9:31 Just FYI :-)

9:31 rrc7cz: cemerick: try redeploying a WAR 100 times on a running Tomcat

9:31 default install, no jvm switches

9:31 cemerick: I presumed you were talking about JRebel as well.

9:31 rrc7cz: oh, no, I don't know what that is

9:31 chouser: have these people who spend their time adding the same features to multiple IDEs (via plugins) really not carved out some kind of common interface to code to?

9:32 cemerick: "no jvm switches" is a silly restriction

9:32 rrc7cz: cemerick: probably, so okay: the switches just delay the problem

9:32 cemerick: chouser: you mean UI-wise and such?

9:32 chouser: no, not UI-wise

9:32 cemerick: rrc7cz: re: permgen? Hardly.

9:32 rrc7cz: cemerick: you can bump up the PermGen space to delay the problem. I believe there are some PG sweeps you can enable, but I think each JVM implements them differently and they never solved the problem 100% for me

9:33 chouser: some programmatic interface that others can use, those of us for whom no IDE UI feels comfortable

9:33 cemerick: oh

9:34 well

9:34 you mean a cmdline interface to an IDE plugin?

9:34 chouser: I dunno. I guess. Or any other kind of common entrypoint.

9:35 cemerick: I've never heard of one. Some plugins do have APIs, insofar as they provide hooks for other plugins.

9:35 chouser: I think you're a market approaching one in this area. :-)

9:36 chouser: :-(

9:36 so lonely

9:36 cemerick: chouser: the hive beckons to you

9:37 chouser: I *try* to conform, really I do! I know it's hard to believe...

9:37 cemerick: that was a ;-)

9:38 Conformity carries a buck of connotations. "Power in numbers" is real, though.

9:38 chouser: I totally agree, which is why I'm not entirely joking

9:40 I'm constantly tempted to write replacement tools from scratch, and with constant vigilence manage to mostly overcome the urge (the occasional dabbling with gentoo, textjure, etc. notwithstanding)

9:41 but there is also danger in the complacency of the mainstream

9:42 cemerick: Tools without a community have vanishingly small benefits AFAICT.

9:42 chouser: A billion MS Foundation Class programmers can't be wrong!

9:42 cemerick: heh

9:42 chouser: cemerick: my tools have communities, I promise.

9:42 cemerick: Of course, VS is a *marvel*, so that comment is slightly ironic. ;-)

9:43 chouser: just because you're not in them doesn't mean they don't exist. :-)

9:43 cemerick: I was referring to the "write replacement tools" thing.

9:43 chouser: oh, right.

9:43 well, the lure there of course is always that if you write a better one the community will form.

9:43 cemerick: whew

9:43 chouser: the siren song

9:44 cemerick: Seeing that sort of thing relatively close up with Clojure, the process holds zero appeal for me.

9:44 chouser: heh

9:44 yeah, that's a really good point

9:45 cemerick: I mean, what would it take to build up a tool with a community like vi or TextMate, or whatever.

9:45 That's a life's work, it seems.

9:46 modulo luck, of course

9:46 * chouser agrees

9:46 chouser: part of why I try to resist such urges.

9:47 but that leads me to prefer the most flexible tools with communities that most encourage hackery

9:47 cemerick: What we really need are more/better vertically-integrated tools, so that mundane BS like builds can be routine and we can focus on what we have useful/valuable expertise in.

9:47 chouser: which is like the antithesis of IDEs

9:48 cemerick: Yeah, I can see that.

9:48 I've always been (and always will be) behind the hackery curve though, so that's a ratrace I had to opt out of early.

9:48 chouser: I've never had valuable expertise

9:49 cemerick: I find that absurdly hard to believe.

9:50 chouser: no, seriously. This is really interesting -- I've never tried to understand my penchants in these regards

10:13 AWizzArd: I have a stream from which I want to read a string. I know that the string is one mio bytes long. Is there something like slurp which takes a limit of bytes to read?

10:17 chouser: AWizzArd: probably best is just use .read

10:18 AWizzArd: chouser: yes, I will probably essentially reimplement slurp, but for bytes.

10:18 slowly filling up a byte array

10:18 chouser: why slowly?

10:19 AWizzArd: i.e: not simply (.read stream buffer 1000000)

10:19 but instead reading byte after byte

10:19 chouser: why?

10:19 clojurebot: http://clojure.org/rationale

10:19 chouser: I mean, why not simply (.read stream buffer 1000000)?

10:19 AWizzArd: chouser: it is a GZIPInputStream. I tried to read a mio bytes from it. But it does not deliver that.

10:19 chouser: does it only fill partially?

10:20 AWizzArd: In the first read it returned 390k bytes. In the second 528k and in the third read the remaining bytes.

10:20 Yes.

10:20 Probably the algorithm of ungzipping needs a few stops in the middle.

10:20 chouser: ok, it'd be best to ask for the remaining buffer size each time (rather than asking for only 1 more byte)

10:20 AWizzArd: yes, I can check how much is .available

10:20 chouser: I'd guess there's no code in clojure or contrib for a fixed-sized buffer like that

10:21 AWizzArd: right

10:21 chouser: just .read and see what it returns

10:21 AWizzArd: Ah yes, .read on the buffer and using its return value, and giving an offset

10:21 chouser: yes

10:22 AWizzArd: int read(byte[] b, int off, int len)

10:22 yes yes, this sounds good

10:23 chouser: exactly. (loop [off 0] ... (recur (- 1000 off bytes-read)))

10:23 no wait

10:23 not that, but you'll get it. :-)

10:25 AWizzArd: yes yes, I am on it already

10:25 btw, there is an interesting design pattern here, for loop

10:25 one of the vars in loop is initialized with an expression that also shows up in the recur call.

10:26 For slurp this is (.read r)

10:26 chouser: yes, that shows up in many languages

10:26 often it can be refactored to only show up in the the recur

10:27 AWizzArd: In my case it is (.read stream result offset remaining) in the loop declaration and the same thing with adjusted values in the recur

10:27 chouser: it shows up much less often in clojure because explicit loops are less common

10:27 AWizzArd: Yes.

10:27 I noticed this however quite a few times already.

10:27 When using LOOP.

10:31 chouser: can you loop with the offset starting at 0 instead?

10:34 AWizzArd: (loop [offset 0, remaining len, n (.read stream result offset remaining)] ...) is what I have

10:34 and it works great

10:34 chouser: but requires repeating your .read code

10:34 AWizzArd: chouser: which is not that bad

10:35 deserialization of a string of length one mio from a gzipped Store now takes just 10.22 msecs vs 6.8 msecs for a non gzipped :)

10:35 fast beast :-)

10:35 chouser: true, not bad.

10:36 another option: (loop [off 0] (when (< off (count buf)) (let [newoff (.read r buf off (count buf))] (when (pos? newoff) (recur (+ off newoff))))))

10:36 AWizzArd: yes, my clojure (de)serialization lib is not drastically much slower than optimized pure java ones

10:37 chouser: hmm yes, I could move the read into a let

10:37 clojurebot: Why are you asking *him*

10:37 AWizzArd: inside the loop

10:38 alexyk: is there a way to tell repl to print say 3 digits after the dot for floating-point numbers?

10:38 chouser: AWizzArd: but perhaps you're implication that a macro could help is correct

10:38 alexyk: in the E notation

10:40 AWizzArd: chouser: well, for this case your ideas put me on the right track. I now just have one read, in a let as the first form inside the loop, and i only refresh the offset and remaining vars in a recur call. Works great and is a bit simpler.

10:40 phenom_: how many languages is too many to learn at once? :{

10:40 alexyk: phenom_: 4

10:41 chouser: alexyk: yes, it's possible. gimme a sec

10:41 alexyk: chouser: kk

10:41 kryft: Hi, what book(s) or other Clojure resources would you recommend to a budding machine learning researcher with a fairly good grasp of imperative and OO programming (mostly with C++ and Python) and a basic understanding of functional programming (I've read some SICP and seen some of the Abel & Sussman lectures)?

10:41 AWizzArd: chouser: this strategy could be used for slurp too I think, resulting in a (loop [] (let [c (.read r)] ... (recur))

10:42 kryft: I know I can learn to churn out some kind of code with just about anything, but because I don't know what I don't know about lisp in general and Clojure in particular, I would like to make sure that I learn how to 'think in Clojure' from the get-go.

10:43 chouser: kryft: I more or less universally recommend the book http://joyofclojure.com/ for reasons that will quickly be obvious to you

10:43 kryft: chouser: :D

10:43 chouser: :-)

10:43 kryft: chouser: I thought your name looked familiar. :)

10:44 alexyk: kryft: I recommend it too as an unbiased clojurer :)

10:44 and a machine learning researcher too... check out incanter.org if you haven't already

10:45 kryft: chouser: That's one of the books I've glanced at, and the free chapter did seem promising.

10:46 alexyk: Oh, wow, no I haven't. :)

10:46 I haven't actually started learning clojure yet, although I've thought about it for months.

10:46 alexyk: kryft: then just peruse the code as you use it, it's the best practices and ML in one :)

10:48 kryft: alexyk: Wow, great. :)

10:48 alexyk: How mature is it?

10:49 alexyk: kryft: I follow it for about a year, very cool, David Liebke is super-responsive and adds everything you need right there. It got contributions and is very alive; also David is a member of Clojure/core which is the most mature group of clojureres, not in terms of old age though :)

10:50 kryft: alexyk: Hehe. :)

10:51 alexyk: That sounds like a project I might want to add to myself once I hone my clojuration skills a bit. ;)

10:51 AWizzArd: chouser: loop can maybe extended to support bindings that are *not* part of the loop itself, but get expanded into a let. They will not be set via recur, but instead the form gets reevaled each time later.

10:52 That would free slurps loop from the double (.read r) and could in principle break this pattern.

10:53 scottj: for ML http://github.com/bradford/infer is interesting too

10:53 chouser: alexyk: Clojure 1.2?

10:53 alexyk: chouser: yep

10:54 chouser: not 1.3-something?

10:54 alexyk: chouser: not on purpose, but if there's a need, why not :)

10:54 chouser: nah

10:54 actually, just realized I didn't need to ask

10:56 (defmethod print-method Double [n w] (.write w (.format (java.text.DecimalFormat. "0.0##E0") n)))

10:57 but that'll do scientific notation for *all* doubles, not just ones that would use it by default

10:57 alexyk: will that do? perhaps you can add an 'if' to fall back to (str n)

10:59 alexyk: chouser: very nice! for now does the trick

10:59 kryft: chouser: When is the dead tree edition coming out, by the way?

10:59 chouser: kryft: The plan is December.

11:00 alexyk: chouser: so (str n) was the default, so I can revert to that?

11:00 chouser: alexyk: yep

11:00 kryft: Oo, I can get 35% off? I didn't think the book was expensive to begin with..

11:00 * alexyk reads all PDF books on iPad now forever

11:00 alexyk: in Good Reader

11:01 kryft: alexyk: I'm going to get a Kindle (or something similar) once I recover from my current bicycle-purchase-induced poverty.

11:01 alexyk: scottj: I thought flightcaster contributed to incanter, now see it's infer... did they split?

11:02 esj: kryft: i'm experiencing a joyful kindle induced poverty (not the device, but the books ...)

11:02 alexyk: kryft: my Kindle DX lays idle for months after iPad arrived, and will probably be in niche use

11:02 kryft: alexyk: Want to sell it? ;)

11:03 scottj: alexyk: don't know, would guess always separate

11:03 alexyk: kryft: although all the kindle books are now used in the kindle reader. Alas, it was a gift and thus I'll keep using it now that my wife grabs the iPad more and more. :)

11:04 kryft: Paradigm-wise (coming to lisp from imperative languages), is there anything major that I should know about that Joy of Clojure doesn't touch on?

11:04 alexyk: kryft: you can get a refurbished DX for $200+, that's what I do

11:04 'd do :)

11:06 kryft: alexyk: Does amazon sell them directly?

11:06 alexyk: kryft: yep

11:06 kryft: but I'd get the iPad, honetsly

11:06 you can iSSH from it into a clojure box :)

11:06 kryft: :)

11:07 I think I'd rather have e-ink and battery life measured in weeks!

11:08 alexyk: kryft: iPad is surprisingly sturdy in terms of battery, the whole day it lasts; and with all the interruptions of real life, e-ink is good for novels only :)

11:08 scottj: and so so pdf rendering and a short break on every keypress

11:08 alexyk: plus, PDF on Kindle used to be abysmal, DX barely cut it

11:08 while iPad rocks

11:09 I now keep iPad with a PDF book on a stand next to Mac, no more command-tab awkwardness

11:09 kryft: alexyk: Abysmal how?

11:10 alexyk: kryft: now easy resizing of small font; iPad is pinch or double-tab

11:10 tap

11:10 not easy on the kindle at all

11:12 ninjudd: wow completion in repl! cake rocks

11:13 mabes: alexyk: more completion than rlwrap provides?

11:13 alexyk: mabes: rlwrap is from a predefined list?

11:14 mabes: alexyk: yes, and your history I think

11:14 alexyk: mabes: didn't try history... but cake infers from the namespace for realz

11:15 mabes: alexyk: I see.. yeah, that is better than rlwrap then

11:15 alexyk: just hit tab! don't be afraid!

11:17 * alexyk gotta go to conj just to buy ninjudd beer or something

11:18 alexyk: anybody driving to conj from the greater Boston area (~4 hour radius)?

11:18 or flying a private plane?

11:23 or sailing/rowing a boat down the coast?

11:23 arkh: is there a way to combine a when-let with cond ? i.e., have the conditional also bind stuff with a let and carry that into the expression paired with the conditional

11:23 chouser: wow, the code Java uses for default formatting of doubles is even hairier than I'd guessed. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/misc/FloatingDecimal.java#910

11:24 arkh: I've played with a custom cond-let a bit. Doesn't seem useful very often.

11:24 alexyk: chouser: scary stuff!

11:26 arkh: chouser: it'd be useful now ; )

11:26 chouser: you have much more clojure experience so I'll take your word for it

11:27 chouser: alexyk: so this might be more comfortable: (defmethod print-method Double [n w] (let [s (str n)] (.write w (if (re-find #"E" s) (.format (java.text.DecimalFormat. "0.0##E0") n) s))))

11:30 alexyk: chouser: ok. Although I find limiting mantissa very useful in all floats, being a former physicist. Seeing 20 decimal places in numeric examples makes me angry and sad, usually, and lamenting screen space :)

11:31 chouser: arkh: this seems to work, if you want to try it out: (defmacro cond-let [[sym] test expr & more] `(if-let [~sym ~test] ~expr ~(when more `(cond-let [~sym] ~@more))))

11:34 arkh: chouser: thank you - I owe you a beverage of your choice at clojure-conj

11:34 chouser: arkh: use it like (cond-let [x] test1 expr-that-uses-x-1 test2 expr-of-x-2)

11:34 arkh: woohoo!

11:34 :-)

11:34 carkh: (.toString ^java.net.URI (-> state :request :uri)) i get reflection warning there in 1.2

11:35 iirc this was not the case in 1.1

11:35 kryft: chouser: I read a few reviews, and it sounds like JoC is definitely the book I'm looking for. One of the reviews suggested that JoC expects the reader to know some clojure already; is that true?

11:36 carkh: if i go (let [^java.net.URI uri (-> state :request :uri)] (.toString uri)) no reflection warning

11:36 is that intended or a bug ?

11:38 arkh: kryft: after reading some of JoC, any expectation of clojure knowledge would become irrelevant after a few readings of the book (imho) If you get JoC, I don't think you'll be disappointed.

11:51 quizme: how do you define a function during runtime?

11:52 (eval '(defn sq [x] (* x x ))) ?

11:52 carkh: yes, but if you need to do this, it means you're doing something wrong

11:54 (most of the time)

11:54 quizme: well i'm just wondering how it would be done

11:54 (hopefully the right way)

11:56 the book Practical Clojure doesn't mention eval, so I was kinda curious.

11:57 carkh: my guess would be that's because it's almost always bad practice using it

11:57 i can't think of a use case

11:57 a meaningfull one

11:57 quizme: well

11:58 how about the human mind

11:58 carkh: heh what about it ?

11:58 quizme: to create a new idea is to create a new function that is able to transform one idea into another.

11:59 you don't have to model it like that

11:59 but

11:59 it seems natural to do so

11:59 carkh: right, you're taking the high level view

11:59 i think that pattern is emergent from very many little state machines (neurons)

12:01 quizme: i realized another weird thing about clojure

12:01 carkh: also that's great thinking about the human mind, but ... at the end of the day, we're not programming such complex things in clojure =P

12:01 quizme: that functions are usual defined as constants, rather than refs

12:02 carkh: function are defined (as constant if you will) then assigned to a var

12:02 in your example, sq is the var

12:02 quizme: yeah

12:02 carkh: (fn [x] (* x x)) is the function

12:02 quizme: i think it would be cool use refs

12:03 carkh: why would you need a ref ? you're not going to need transactional access to it

12:03 quizme: because then you could group chunks of dependent functions into a transaction, so that you could update your system in real-time

12:03 clojurebot: functions are maps

12:03 carkh: ah true

12:04 but what of the live data

12:04 quizme: what about it ?

12:04 carkh: what i mean is : hot code swap is hard

12:05 there are not only the functions, but the data upon which they work

12:05 quizme: yeah

12:05 well

12:05 let's say it's voice data

12:05 and you implement a new algorithm to process voices more efficiently

12:05 then you could update your system while people were talking

12:06 and people would suddenly notice the quality of their calls getting better.

12:06 carkh: right there are good reasons to want that, but i'm not sure clojure is the very best tool for that

12:06 i'm not sure the JVM is very good at that

12:07 quizme: i guess it depends on the problem domain.

12:07 carkh: looks like you want to use erlang =P

12:07 quizme: well i was just trying to make clojure cool like erlang

12:08 not that erlang is cooler

12:08 carkh: i think they're very different languages both cool, but for different use cases

12:08 quizme: yeah

12:09 carkh: for your voice example, in clojure, i guess you would have to use some RTP proxy in front of your app, launch the updated version, then reroute to it

12:10 quizme: oh my gosh what's an rtp proxy

12:11 carkh: well you're talking about voice ... i guess the transport would be rtp =P

12:11 i don't know much about all that =)

12:12 anyways i have this customer, whith quite a few sub-customers all using the same application of mine, i would never dare hot updating that

12:13 alexyk: can you do lein repl from several sessions with the same JVM? cake repl apparently does it!

12:14 technomancy: alexyk: sure; lein repl starts a socket repl; just telnet in

12:14 alexyk: technomancy: OK

12:15 technomancy: when cake fails to gets its own deps, I do lein deps, and the elder brother saves the day, begrudgingly :)

12:15 technomancy: heh

12:16 toshiblue: hi all--newbie---just trying to do the string-calc kata- and having a lot of trouble running the tests. I have a feeling my 'add' code is not loading properly - getting the following error:

12:16 ERROR in (add_with_empty_string) (core.clj:6)

12:16 expected: (= 0 (add ""))

12:16 actual: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn


12:17 alexyk: technomancy: how do you blink parens in lein repl?

12:17 technomancy: alexyk: M-x telnet followed by M-x show-paren-mode I guess

12:18 it depends on the client

12:18 alexyk: technomancy: I mean, lein repl just blinks parens in my shell (zsh)...

12:18 technomancy: I think that would need to be handled by rlwrap; I don't know how to enable that

12:20 ,(meta (fn not-so-anonymous []))

12:20 clojurebot: nil

12:20 technomancy: that, sir, is weak.

12:22 quizme: is there another way to create a function during runtime besides using eval?.... you could write a function that generates functions..... any other (general) way (besides stuff like comp or partial)?

12:24 carkh: quizme: the usual way is to make closures

12:24 then pass the closure to your call site function

12:25 you surely know of the canonical example

12:25 quizme: carkh: you mean using "fn" ?

12:25 hugod: Its probably come up before, but I can't find an answer: are their plans to get contrib into maven central?

12:25 quizme: carkh what's the canonical example?

12:25 carkh: ,(let [adder (fn [x] (fn [y] (+ x y)))] ((adder 3) 4))

12:25 clojurebot: 7

12:26 carkh: in some way the form (adder 3) "compiles" a function

12:28 quizme: carkh: ok. thanks.

12:29 carkh: the example is very simple, but you could go wild on that principle

12:29 hsuh: technomancy: clojure-test-mode tells me i had 2 failures but highlights nothing... any idea ?

12:30 technomancy: hsuh: it's certainly not perfect. if you have a good repro case feel free to open a ticket.

12:30 hsuh: k

12:30 technomancy: I haven't really touched it much in over a year; it's due for a refactoring

12:36 TakeV: How do you do something like "import java.awt.event.*" in clojure?

12:38 chouser: kryft: arkh's answer was good. Basically, we didn't have room to be a complete Clojure intro. If you've never done any Clojure or other lisp, the first chapter or two might be at a challenging, but once you've gotten that far we settle down a bit to dig into the meatier points we want to make.

12:38 a challenging pace

12:38 TakeV: no globby imports in Clojure, sorry

12:39 TakeV: but you can (import '(java.awt.event Foo Bar Baz))

12:40 TakeV: chouser: Ah, alright. Thanks.

12:41 Hmm, is there a conscious design decision for the lack of global imports?

12:41 chouser: yes, I believe so.

12:41 I for one am grateful. :-)

12:41 it bugs me to not know where classes are coming from, what their full name is.

12:41 * TakeV nods

12:42 TakeV: I can see that. Though it does make it annoying to port certain java code into clojure.

12:42 chouser: yeah, but I just blame the Java code

12:42 carkh: hum is there some reason why recompiling defmethods still uses old methods ?

12:43 chouser: which doesn't speed the porting, but makes me feel a little better. :-)

12:43 TakeV: :P

12:43 chouser: carkh: not sure what you mean

12:44 carkh: i have this file where i define a frag multimethod, and 2 frag methods, i put some log statements but they wouldn't show, i had to restart the jvm

12:45 and now i removed the logging, but it still show =/

12:45 the multimethod is used at compile time

12:45 (from another file)

12:45 dakrone: toshiblue, what's the source for 'add' look like?

12:45 carkh: and i recompile everything every time

12:48 chouser: carkh: I'm still not quite sure what you mean. I redefine using defmethod all the time and start using the new version right away

12:48 carkh: perhaps a minimal example that demonstrates the problem would be instructive

12:48 carkh: i do that all the time too ....but i updated to 1.2

12:48 maybe swank acting up ?

12:49 chouser: alexyk: (defmethod print-method Double [n w] (let [s (str n)] (.write w (if (re-find #"E|\d{4,}" s) (.format (java.text.DecimalFormat. "0.0##E0") n) s))))

12:56 carkh: restarting emacs and everything fixed it =/

12:58 kryft: chouser: Ok. I've had some scheme exposure (parts of SICP and quite a few of the Abelson-Sussman lectures), so I guess it shouldn't be too hard, especially with the many free (but not-too-meaty) tutorials available online.

12:58 chouser: kryft: I think you'll find we don't waste your time. :-)

12:59 kryft: chouser: I appreciate it. =)

13:01 chouser: I bought the book already. I noticed a couple of typos in the first chapter, but I assume the book is still being proofread?

13:01 chouser: yep, going through copyediting as we speak.

13:01 also a final techincal-correctness review.

13:01 kryft: Oh, one of them was actually corrected (cheif -> chief) in the version I just downloaded. I guess the freely available version was older.

13:02 Ok.

13:03 Anyway, seems great overall. :)

13:03 chouser: :-) thanks. If you find anything worth commenting on beyond what copyediting is likely to catch, feel free to post on the Manning forum.

13:04 we'll get one last shot at making changes before they go to press

13:04 kryft: Ok. Will I have access to the final version of the ebook once the book is published?

13:04 chouser: yep

13:04 kryft: Great.

13:22 toshiblue: dakrone: I think I've got it....I've had a restart of my machine, swank, emacs since yesterday and that seems to have cleared whatever it was.....

13:22 thanks

13:25 grettke: question for you emacs guys... do you use clojure mode with or without SLIME? I don't use slime... I'm too simple.

13:27 mrBliss: grettke: look at this cheat sheet to see some of the handy functions you're missing out on: http://www.pchristensen.com/slimecommands.pdf

13:28 grettke: mrBliss: thanks

13:51 raek: grettke: for me, interactive development is essensial. I can't imagine how I would code the way I do now without slime.

13:52 instead of having to switch to the repl, type (in-ns 'namespace-of-source-buffer) and paste the code, I simply press C-M-x

13:55 I can't code without slime... I'm too simple. :-)

13:57 grettke: raek: lol point taken!

13:58 dnolen: raek: are you the one that had those nice .emacs customizations for paredit and clojure-mode in the repl?

13:59 grettke: dnolen: which ones? why are they nice?

13:59 raek: I use the the master branch of technomancy's clojure-mode

13:59 kryft: I can't live without vim(-like keybinding - I've considered emacs with vimpulse or whatever it was called)

14:00 raek: M-x customize-variable RET clojure-mode-use-backtracking-indent

14:00 makes defrecord and friends indent correctly

14:01 as for paredit: this is the inly customization I have: http://gist.github.com/612010

14:03 it makes paredit insert a matching closing culty bracket in the same way it does with with round and square ones

14:03 doesn't seem to work with the ELPA version of paredit though...

14:05 alexyk: when do things start at clojure-conj on the 22nd, and when do they end on the 23rd?

14:07 there seems to be no progarm yet on the site...

14:07 kryft: alexyk: Is that some kind of conference?

14:07 alexyk: kryft: clojure-cong.org

14:07 conj.org

14:08 sorry for the typos :)

14:08 http://clojure-conj.org/information

14:08 kryft: Ah. :)

14:10 dnolen: grettke: just getting rich lisp editing in the REPL

14:25 bartj: @future doesn't seem to give the output of the last statement in the function

14:25 testing futures code here: http://pastebin.org/30656

14:25 I have given the actual output and the intended output

14:25 cemerick: ,@(future 5)

14:25 clojurebot: 5

14:30 cemerick: bartj: I get your expected output here

14:30 oh, wait, no I don't

14:31 bartj: You want (future (save batch))

14:31 bartj: :)

14:32 , (doc future)

14:32 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

14:33 bartj: makes sense

14:33 but, I wonder why (future save batch) even compiled!

14:34 cemerick: ,@(future 1 2 3 4 5 6)

14:34 clojurebot: 6

14:35 cemerick: it takes any body of expressions, and evaluates them

14:35 bartj: ,@(future blah1 blah2 blah3)

14:35 clojurebot: java.lang.Exception: Unable to resolve symbol: blah1 in this context

14:36 bartj: cemerick, yes...but, I gave (future save batch)....and save isn't defined anywhere

14:36 cemerick: it is on line 3?

14:37 bartj: cemerick, sheepish grin

14:37 cemerick, thanks a lot

15:18 fhd: Hi. I've asked about a shorter alternative to (require 'long.namespace) (ns long.namespace) yesterday, and I found one:

15:18 (require '[long.namespace :as n])

15:18 (n/some-function)

15:20 Just wanted to share in case someone wanted the same :) Bye

15:48 LauJensen: Good morning folk - Just got back from hearing Rich and Stu in Aarhus, DK :)

15:49 ataggart: They're in Denmark?!

15:49 joly: welcome back :) good talks?

15:49 ataggart: that explains why they haven't applied my patch!

15:50 kotarak: ataggart: haha. Applying patches is not a tradition in the clojure world.

15:51 LauJensen: joly: Yea very good talks - I really get the sense that Rich knows what he's talking about when it comes to Clojure :)

15:51 And Stu was smoking

15:51 ataggart: yea

15:54 AWizzArd: LauJensen: what did they say?

15:55 And what was it that Stu was smoking? ;)

15:55 LauJensen: AWizzArd: Rich talked about 1.3, Statics, Equality and Pods (from questions in the audience, namely me). Stu talked about pitching Clojures OO features to OO addicts

15:56 Cliff Click talked about the troubles of Concurrent programming on many levels, and some interesting solutions

15:56 kotarak: Pfff.. conference attendees know more about Pods than the community itself. :/

15:56 AWizzArd: kotarak: not really :)

15:57 At least I am a user of them.

15:57 I started using Cells only days after they were gisted.

15:57 Maybe I am the only user so far.

15:57 LauJensen: kotarak: did I detect a little whine? :)

15:57 joly: Is there a link for a Pods description? I've only heard the term a few times

15:57 LauJensen: You have to attend more conference, OR conj labs

15:57 kotarak: LauJensen: indeed

15:58 LauJensen: indeed a whine, I mean. Will wait for a EU conj.

15:58 LauJensen: Yea dont hold your breath, I asked Rich about it, he said the numbers are vastly on the US side

15:58 AWizzArd: LauJensen: I would like a switch in the compiler which will try to make ^:static out of every function where possible

15:58 LauJensen: Man, he demoed the warn on reflection for statics, that stuff was crazy

15:59 AWizzArd: in what way crazy?

15:59 LauJensen: ** Warning, your loop coerces to Object on var 'accumulation' on recur

15:59 Extremely accurate

15:59 kotarak: Ah. My uber-loop. :)

15:59 AWizzArd: yes, good

15:59 kotarak: today chouser and I discovered that loop could be improved

15:59 LauJensen: joly: He's the description for Pods : http://www.assembla.com/wiki/show/clojure/Cells

16:00 joly: LauJensen: cool, I'll check it out :)

16:00 ataggart: but the logic is currently a little overconstrained

16:00 kotarak: AWizzArd: in which way?

16:00 LauJensen: ataggart: in which way ?

16:00 AWizzArd: kotarak: there is sometimes a pattern in loop in which an expression shows up inside the bindings and in the recur

16:00 for example, see slurp

16:00 (loop [c (.read r)] ... (recur (.read r)))

16:01 ataggart: you can get WOR emessages that arg is byte when it is expected to be a long, so it boxes everything

16:01 AWizzArd: Today I stumbled upon this while I was implementing slurp-bytes

16:01 nickik: @kotarak the conffreaks guy takes for ever to upload that video

16:01 AWizzArd: yeah, LauJensen should not chat so much but instead better upload a few videos (:

16:02 nickik: mmmh?

16:02 LauJensen: AWizzArd: So whats the optimization of that pattern ?

16:03 AWizzArd: LauJensen: the trick is to move out the var outside of the loop, and put it into a let, directly under the loop

16:03 (loop [] (let [c (.read r)] ... (recur))

16:04 Today I had the same. I started off with (loop [offset 0, remaining len, n (.read buffer offset remaining)] ...

16:04 ataggart: Example of "over-constrained": IllegalArgumentException recur arg for primitive local: i is not matching primitive, had: byte, needed: long

16:04 that bytes aren't allowed to fit into a long is a bug imo

16:04 LauJensen: ataggart: no auto promotion of any kind is possible with primitives

16:04 AWizzArd: in the recur I would have to have something such as: (recur (+ offset n) (- remaining n) (.read buffer (+ offset n) (- remaining n))

16:04 ataggart: it is possible

16:05 just not implemented

16:05 LauJensen: ataggart: not according to Rich, he said so explicitly today

16:05 kotarak: AWizzArd: yo. Used that strategy before.

16:05 AWizzArd: this means doubling the (+ offset n) thing, also for remaining

16:05 kotarak: good

16:05 What I did was moving the .read out of the loop and put it into a let, directly under the loop

16:05 loop over let is the name of this design pattern

16:06 ataggart: Well, I submitted a patch that allows for full widening conversion of primitives

16:06 AWizzArd: named after its inventor, me :)

16:06 LauJensen: AWizzArd: Excuse me for asking, its been a long day, whats the gain in that ?

16:06 AWizzArd: anyway, there could be a loop2 that expands into the correct pattern, or a non-breaking extension to loop

16:06 LauJensen: the gain is that the code becomes more readable and one can save to repeat things

16:07 As you see, i have a .read in my loop bindings *and* in the recur

16:07 joly: LauJensen: don't need to repeat (.read r) in multiple places

16:07 alexyk: technomancy: when I was asking about two lein repl against the same JVM, I mean, can you say lein repl in another shell while in the same directory as the original one and get another repl against the same JVM like cake?

16:07 AWizzArd: slurp is doing the same, it has (loop [c (.read r)] .. and (recur (.read r)))

16:07 bmh: If I'm using a namespace and qualifying it 'as', what's the crumulent syntax for throwing an except in there?

16:08 (:use [clojure.contrib.io :as io :except spit]) didn't seem to do the trick

16:08 AWizzArd: I noticed that this pattern shows up from time to time when using loop. Now chouser and kotarak confirmed that they too stumbled upon this

16:08 ataggart: require goes :as, use goes with :only

16:08 bmh: ^

16:08 kotarak: AWizzArd: I think the point is, that (.read r) is independent of the loop. So it doesn't need to be there.

16:08 AWizzArd: kotarak: yes

16:08 bmh: ataggart: Thanks

16:09 kotarak: Always be minimal.

16:09 AWizzArd: it’s just that it often is the first idea to put it into the loop

16:09 hiredman: AWizzArd: in some cases you can replae with something like (take-while identity (repeatedly #(.read something)))

16:09 AWizzArd: and if one does not want to, one needs this loop-over-let-pattern

16:09 hiredman: yes, it is often nicer when I can go without the loop and use a higher-level construct

16:11 nickik: has anybody used lazytest?

16:12 LauJensen: nickik: I think stuartsierra has :)

16:13 nickik: @LauJensen don't think he likes it :)

16:17 this just dosn't work --> java -cp "src:test:classes:lib/*:lib/dev/*" lazytest.watch src test

16:27 bartj: I have triggered a bunch of "futures"

16:27 and I don't really care about the return val of those futures

16:28 but, I want all of them to finish executing

16:28 one option is for me to do a: @future

16:28 can I also do a call to (await)

16:29 or is await used only in the case of agents and should not be used for futures

16:35 LauJensen: await is for agents

16:35 deref is for blocking until future returns

16:36 freakazoid: it's slightly scary that deref sometimes blocks

16:37 LauJensen: makes sense though

16:37 freakazoid: having stuff in general that never blocks with some types and may block with other types is scary.

16:37 I like having functions/syntactic forms that I can just tell with my eyeballs will not block.

16:40 tomoj: LauJensen: https://gist.github.com/d3efe42b44bb0385c69f

16:40 examples of paredit-convolute-sexp usage

16:40 what do you think?

16:40 LauJensen: freakazoid: if your eyeballs can tell a future from another ref type, you should be good to go

16:41 tomoj: the video isnt playing :)

16:41 dnolen: LauJensen: future and promise

16:41 tomoj: heh

16:41 I'm working on the video

16:41 have to take notes on what to record

16:42 LauJensen: tomoj: Its hard for me just to read, not knowing the functions individually, so I think I have to get par-edit going and tag along :)

16:42 freakazoid: LauJensen: your eyeballs can determine types in a dynamically typed language without having to look at every place a function is called from?

16:42 LauJensen: Also, just looking at the conversion Im thinking, that'll take me 2 seconds to re-write with just standard emacs commands, how long does that sequence take you to hammer out?

16:43 freakazoid: The semantantics for blocking/non-blocking are completely different

16:43 tomoj: LauJensen: 2 seconds?

16:43 that's why I posted it

16:43 freakazoid: LauJensen: I agree it's not a huge deal, since it's unlikely someone will pass in a future when you expect a ref

16:43 tomoj: how do you do the conversion?

16:44 in actuality I hardly ever use paredit-convolute-sexp

16:44 LauJensen: C-k C-n M-f^3 C-y something something

16:44 :)

16:44 tomoj: and then you have to fix your parens?

16:44 LauJensen: tomoj: but that only takes the last 0.1s

16:45 tomoj: I'm just collecting facts

16:45 LauJensen: And I appreciate it. Im just telling you the reason for my hesitance. But if your screencast shows me that you're faster than me, Im switching to paredit, no doubt about it :)

16:46 tomoj: do you use rainbow mode or something like it

16:46 or just show-paren-mode?

16:46 LauJensen: tomoj: just show-paren

16:46 I would never, ever, use rainbow parens :)

16:47 kotarak asked me, does clojure-mode have rainbow parens? I said no. But why? he asked. I said "because mostly its men who use it"

16:47 So he stopped bragging about vim-clojure for a little while

16:48 kotarak: -.-

16:48 LauJensen: you have to accept your feminin side. Geez...

16:49 LauJensen: haha

16:49 So un-kraut like

16:49 tomoj: you can change the colors so they're not rainbow :P

16:49 I just use show-paren-mode too though

16:49 but I never have to balance

16:54 LauJensen: mind if I continue to ping you for comment?

16:54 LauJensen: not at all

16:54 scottj: tomoj: cool didn't know about convolute. it has a small bug though as at (foo (bar|)) with no space between r and ) it yields (bar(foo ))

16:57 esj: LauJensen: "...men who use it" LMAO.

16:57 LauJensen: :D

16:58 esj: Its all good fun, a couple of weeks from now kotarak will treat me to some roasted apples in the heart of Frankfurt, right old buddy? :D

16:59 kotarak: LauJensen: yup. :)

16:59 esj: LauJensen: I think you may be on the hook for some weissbier first

16:59 kotarak: esj: bleh. Weißbier. :( Äppelwoi!

17:00 esj: oh dear, if its anything like cider....

17:00 lancepantz: roasted apples eh? that sounds tasty

17:01 kotarak: esj: yeah. roughly. But cider has a sweet taste. Äppelwoi / Apfelwein is more sour.

17:01 lancepantz: yup. :)

17:01 lancepantz: i need to go to europe

17:01 LauJensen: lancepantz: come to the next conj labs :)

17:01 lancepantz: i wonder if i could get work to pay for it :P

17:02 esj: lancepantz: yeah - roast apfels. No rainbows, though.

17:02 LauJensen: lancepantz: If you cant, give me their phone # and I'll talk to them

17:02 Its a sensible investment

17:03 lancepantz: i can just see the expense report $1,500 -- roasted apples

17:03 LauJensen: hehe, then you KNOW that kotarak was involved

17:04 lancepantz: :P

17:04 LauJensen: $1,500 roasted apples in funny colors

17:04 kotarak: But tasty!

17:04 LauJensen: I wish I could talk about some famous danish meal, but we have no tradition for food :)

17:05 esj: kotarak: you gotta tell me how to roast these apples, i've got hundreds in my garden right now, and there's only so much apple pie 1 man can eat.

17:05 lancepantz: oh man, i used to have plumb three in my 2m x 4m yard

17:06 during plumb season i couldn't even throw them away fast enough

17:06 LauJensen: esj: haha

17:06 lancepantz: i ended up bags full of them in the freezer

17:06 LauJensen: lancepantz: you should make smoothies

17:06 lancepantz: the best was sangria :)

17:07 kotarak: esj: you can get some ideas here: http://bit.ly/96QcNb

17:07 esj: Sangria !

17:07 lancepantz: best i've ever had

17:07 kotarak: Although the english translation looses a bit in details

17:07 esj: hmmm..... that's german.

17:07 i think i can speak german when very drunk

17:07 but am assured by all those who can, that I am mistaken

17:08 kotarak: all the recipes my anglo-google know for roasting apples seem to include a duck as well.... can't be correct.

17:08 LauJensen: esj: nobody can master german, not even german people

17:09 In 'high school' I had a german guy do my homework for me, he failed a least one of my papers

17:09 (german homework, that is)

17:09 esj: LauJensen: yeah, I can do dutch, and when drunk the hamming distance to german seems less

17:09 kotarak: esj: there is also an english translation in there. (in red) But it really is much less details :/

17:10 esj: kotarak: I'm going to get to the bottom of this !

17:15 bartj: kotarak, if it means anything, I use vimclojure

17:16 LauJensen, thanks for the clarification re: futures

17:16 LauJensen: np

17:17 kotarak: bartj: nice. I hope you find it useful.

17:19 bartj: kotarak, I think it doesn't add the closing parenthesis like paredit - which has been my biggest gripe

17:20 kotarak: bartj: It doesn't. There are a plethora of plugins like autoclose and friends. There is no real need for vimclojure to provide that. Although the "close inner form" functionality is on my radar.

17:21 bartj: kotarak, would you consider doing a screen-cast / tutorial of how your vim + clojure setup looks like ?

17:22 kotarak, the way LauJensen did with his emacs setup ? Clojure users who use vim would love it.

17:23 kotarak, which plugin do *you* use for auto closing parens ?

17:43 lypanov: imagine a hypothetical situation, you lose your job, and want to do something useful for clojure within a 1-2 month period.

17:44 so, what should i do? :P

17:44 technomancy: lypanov: that happened to me

17:44 I wrote the Clojure PeepCode that month. =)

17:45 lypanov: technomancy: +1

17:46 up to now i'm debating: playing with getting a prototype clj -> js translator working for a minimal subset to learn more about how that might be done in the future

17:46 : getting clojure running on top of llvm.

17:46 or um... playing with some sort of pallet based thing.

17:47 freakazoid: how about writing a MOO?

17:47 lypanov: freakazoid: a game hater is probably not the best person for that hehe

17:47 * lypanov likes tetris

17:48 maacl: astoddard: Did you ever get anywhere with org-babel-clojure

17:48 freakazoid: Most MOOs were social

17:48 * hugod votes for some sort of pallet based thing

17:48 freakazoid: and I just meant the platform

17:48 lypanov: hehe

17:49 freakazoid: i would like to make a clojure / websocket based wave client.

17:49 hugod: i'd like to make a self healing thing.

17:49 freakazoid: google wave? isn't google abandoning that?

17:59 jjido: I am thinking of using metadata to hold type-related information

17:59 lypanov: freakazoid: google maybe. but the idea rocks.

17:59 * lypanov can't imagine living without it honestly

18:00 jjido: does metadata get lost when passing a variable around?

18:01 and using assoc or merge on a record

18:03 freakazoid: lypanov: I agree. Google just didn't seem to have a coherent vision around it.

18:04 duck1123: the emacs wave client has some clojure in it, but the maintainer gave up when google did

18:05 freakazoid: hard to blame them

18:05 (the maintainer)

18:05 duck1123: well, it had some clojure, it appears to be all emacs lisp now

18:06 freakazoid: How did it run the clojure bits? It depended on your having a JVM?

18:06 dnolen: jjido: using metadata for type info is supported

18:06 ,(type (with-meta {:foo 'bar} {:type ::my-type}))

18:06 clojurebot: :sandbox/my-type

18:07 dnolen: jjido: metadata is sticky

18:08 jjido: dnolen: I can put whatever I want there right? and if I put a keyword type makes it into a variable?

18:09 dnolen: jjido: not it's just a namespaced keyword not a variable, but you can put whatever you want there in the metadata map

18:11 kotarak: bartj I don't use auto-closing. I personally find it more annoying than helpful. Hitting the closing paren repeatable is good enough for me.

18:11 jjido: ,(type (with-meta {:foo 'baz} {:type :last}))

18:11 clojurebot: :last

18:17 jjido: is it costly if I put a large record in there?

18:18 dnolen: jjido: dunno, but with a profiler you'll be able to easily see if that's a problem

19:28 tomoj: is there an asynch-io based DataInputStream?

20:00 amalloy: tomoj: java.nio has it. i'm not sure if there's a clojure wrapper

20:02 http://download.oracle.com/javase/6/docs/api/java/nio/package-summary.htm - it uses "Buffers" and "Channels" instead of streams, since the stream interface is blocking

20:04 tomoj: righ

20:04 shoot

20:04 aleph wraps it some

20:04 but I'm not sure if in the right ways

20:04 hiredman: uh

20:04 tomoj: I wasted all this time writing to DataInputStream

20:04 hiredman: א wraps netty

20:04 which is not the same thing as nio

20:06 tomoj: hiredman: ok

20:06 does netty wrap nio?

20:06 "nio" is ambiguous between java.nio and some kind of class of software which includes java.nio and netty?

20:07 hiredman: nio is java.nio

20:08 netty maybe be built on nio

20:08 tomoj: "Netty - the Java NIO Client Server Socket Framework"

20:08 ok

20:08 so aleph maybe wraps it indirectly

20:08 hiredman: there are also nio "replacements" like xnio and things that correspond to netty for those

20:09 tomoj: ah

20:09 I will stick with netty for aleph

20:10 ossareh: hey, I need to look up a var def'ed in a namespace that doesn't exist at compilation time. How can I get around that?

20:11 or, more accurately, how can I tell the compiler to not try to eval it until runtime? lein uberjar is compiling all the files and it dies when looking up that var.

20:12 technomancy: ,(doc ns-resolve)

20:12 clojurebot: "([ns sym]); Returns the var or Class to which a symbol will be resolved in the namespace, else nil. Note that if the symbol is fully qualified, the var/Class to which it resolves need not be present in the namespace."

20:12 ossareh: thanks phil!

20:12 technomancy: sure thing

20:13 tomoj: ooh, that is nifty

20:13 I never thought about it before

20:13 ossareh: its how I'm achieving per jvm conf files for various clients

20:14 tomoj: interesting idea

20:15 how do you pass the ns/var to use when loading the conf?

20:16 ztellman: tomoj: what are you trying to do with nio?

20:17 tomoj: implement a proprietary tcp protocol

20:18 ztellman: tomoj: well, I'd hope that aleph could do whatever you need

20:18 tomoj: that data is like <packet-1-byte><..DataOutputStream style fields determined by packet-1-byte><packet-2-byte><....>

20:18 yes

20:18 me too

20:18 ztellman: if not, please let me know

20:19 tomoj: unfortunately I don't understand it yet

20:19 ossareh: tomoj: does it have to be nio? I found blocking to a) be easier to prototype with, and b) perform better is a very important set of circumstance (i.e. not thousands of connections)

20:19 tomoj: hmm

20:20 ossareh: sounds like you're at some degree of investigation stage, I'd definitely work using blocking first

20:20 tomoj: aleph is just so cool that I want to use it

20:20 ossareh: haha =) fair enough!

20:20 tomoj: I wrote a blocking parser already

20:20 but no server implementation

20:20 ztellman: ha

20:20 tomoj: what do you mean no server implementation?

20:20 tomoj: I mean, I can read logs of the tcp data going between server and client

20:20 but I cannot be a server or client yet

20:20 ztellman: ah

20:20 tomoj: just a proxy

20:21 ossareh: tomoj: the ns is loaded via (load-script "./config") which reads the file - important thing for me is that the file is outside of the jar.

20:21 tomoj: ah, hmm

20:21 I was just thinking about that

20:21 I was thinking you might specify a config file when building

20:21 but outside of the jar would be nice for chef

20:22 ossareh: yeah, exactly

20:22 ztellman: tomoj: hopefully the wiki will give you some idea of how aleph is meant to be used

20:22 tomoj: yeah, just need to reread it. eventually I hope I'll achieve enlightenment after reading through the wiki?

20:22 ztellman: if not, send any questions you have to the mailing list

20:23 tomoj: if there are things that are confusing after you've read through it, let me know what they are

20:23 tomoj: I'm just dumb

20:23 ztellman: the wiki's nowhere near as good as I'd like it to be

20:24 understanding how you're confused will help me make it better

20:24 tomoj: oh, great

20:24 I was confused about how to use a tcp-client

20:24 now I see the wiki explains

20:24 ztellman: yeah, that's a recent addition

20:24 tomoj: :D

20:24 ztellman: like I said, the documentation is a work in progress

20:25 tomoj: I quite like the documentation made so far

20:25 ossareh: technomancy: quick question for you, is there some way I can switch on debugging or something in lein - it takes about 4 minutes to copy 12 jar files when doing uberjar - it reports that the files are going into lib/dev and the files that are in there... are not 4 minutes worth of copying.

20:25 tomoj: are pods or cells relevant to aleph?

20:25 (both are mysteries to me)

20:25 ztellman: not especially, I think

20:26 tomoj: well, as there seem to be no huge performance difficulties with the way aleph is now, great

20:26 ztellman: as far as I understand them, pods are about making things immutable even when dealing with mutable data structures

20:27 aleph is all about side effects

20:27 anyways, I've got to run

20:27 tomoj: thanks for the help

20:27 ztellman: but don't be shy about questions

20:28 they really do help me

20:29 tomoj: I think documentation writers should make it a habit to put use:only/require statements at the top of introductory examples

20:30 hiredman: it's a problem in the java comunity too, examples always leave out the imports

20:30 tomoj: I end up digging into project's sources over and over to remember where the functions are

20:30 yeah

20:30 and no .* in imports, dammit

20:30 in examples

20:30 ossareh: whats the beef with .*?

20:30 tomoj: (analogously no :use without :only)

20:30 moogatronic: tomoj: I run into this problem with ever new language i'm learning as well. =)

20:31 tomoj: ossareh: I'm looking at the example in which several functions are used. I want some of them

20:31 ossareh: i understand from a clj pov

20:31 I didn't from a java pov

20:31 tomoj: with .* it's the same

20:31 just classes instead of functions

20:31 and packages instead of namespaces

20:31 if it's only one .*, that's not so bad

20:31 but if it's more than one, you have to guess or look up which package a class comes from

20:32 ossareh: ah, right - I see your angle now.

20:32 tomoj: I just want to know by looking at the readme so I don't have to mine down to ~/code/clojure/xxx/src/main/java/com/yyyy/foo/bar/

20:33 but hey, ambiguous examples are better than no examples

20:34 technomancy: ossareh: no debugging hooks exist right now unfortunately.

20:34 if you can make the project.clj public you could open an issue on it

20:34 or if you can repro on a project.clj that you can paste somewhere public

20:35 ossareh: I think I can do one of those for sure

20:35 thanks!

20:35 technomancy: sure; I'll see what I can do

20:36 ossareh: I'm gearing up to write a hook soon - excited :->

20:42 tomoj: I am thinking of building a dsl which compiles to a dsl, am I crazy?

20:42 jcromartie: yes

20:42 tomoj: think of thrift

20:43 well, maybe not

20:43 I was thinking of writing a language you'd use to write things like thrift clients/servers

20:43 but not necessarily thrift, could be other binary formats

20:43 ossareh: you mean like protobuf?

20:43 tomoj: could be protobuf too

20:44 you'd use this language to write implementations of protobuf, thrift, whatever in clojure

20:44 ossareh: sounds meta++

20:44 tomoj: and whatever the format, they all share some protocols

20:44 which let you use them in e.g. aleph

20:45 crazy, eh

20:53 KirinDave: Does anyone know how to make slime's complete-symbol more namespace-aware?

20:53 tomoj: what is missing?

20:54 KirinDave: It's not completing symbols from outside the current namespace?

20:54 tomoj: you mean like "bar/ba|" TAB completes to bar/baz?

20:54 KirinDave: It doesn't, for me.

20:54 tomoj: right

20:54 KirinDave: But also, uses from other namespaces

20:54 Like I have a .syntax namespace that holds the macros

20:55 tomoj: I definitely get completion on uses from other namespaces

20:55 KirinDave: I currently don't.

20:55 tomoj: did you load the file?

20:56 does the file's ns declaration have an ns docstring?

20:56 KirinDave: No.

20:56 tomoj: to which?

20:56 you must load the file

21:01 how does leiningen insert <git> and tag info into the pom?

21:01 "Your branch is behind 'origin/master' by 258 commits, and can be fast-forwarded."

21:04 KirinDave: tomoj: I did load the file.

21:05 tomoj: I can get completion to work on the repl, but not in the buffers.

21:05 technomancy: tomoj: it does a partial parse of .git/config; see src/leiningen/util/maven.clj

21:05 tomoj: KirinDave: C-h k the key you're using to complete

21:05 technomancy: cool

21:06 KirinDave: slime-complete-symbol

21:06 tomoj: does a leiningen client have access to that info for dependencies?

21:06 I mean a "client" to the dependencies, not building them

21:06 technomancy: tomoj: you can always open the jar up and read the pom; that's the only way

21:07 gotta jet; feel free to ask on the mailing list

21:07 tomoj: thanks

21:07 KirinDave: tomoj: https://gist.github.com/c9c8d6cb47fdc5416993

21:10 tomoj: KirinDave: swank-clojure version?

21:10 I am having success with 1.3.0-SNAPSHOT

21:11 KirinDave: I'll try 1.3.0

21:14 tomoj: I wonder what I did to offend slime. Doesn't work for me.

21:15 tomoj: KirinDave: when you type C-c M-p in the buffer, what namespace is displayed by default?

21:15 (the buffer's namespace?)

21:15 KirinDave: C-c M-p prompts me for a package name

21:16 tomoj: right

21:16 do M-: (slime-current-package)

21:16 KirinDave: there is no default

21:16 tomoj: this is the problem

21:16 (do that while in the buffer)

21:17 KirinDave: how did you load the file? C-c C-k?

21:17 KirinDave: (user)

21:17 While in that buffer.

21:17 erikcw1: I've been playing with work ( http://github.com/clj-sys/work ) -- trying to setup a thread pool that will work through an SQS queue. I have the pool size set to 10, but from my logs it looks like only a single thread is running. Does anyone know what I may be missing?

21:20 tomoj: hmm

21:20 does your protocol-machine macro mess with namespaces?

21:20 KirinDave: No.

21:21 tomoj: did you get slime from ELPA?

21:21 KirinDave: Yes.

21:21 tomoj: version?

21:21 KirinDave: I think so anyways.

21:21 tomoj: wow, I'm using 20091016

21:22 I'm surprised mine works and yours doesn't

21:22 KirinDave: I was too

21:22 I am updating.

21:34 tomoj: I updated, but it still fails. It's like it doesn't understand it's not in user. :\

21:35 tomoj: how'd you update without restarting emacs?

21:36 KirinDave: I restarted emacs. :)

21:36 tomoj: oh

21:36 I just assumed you used erc

21:37 KirinDave: tomoj: It's like it doesn't get it http://cl.ly/2iKv :)

21:39 tomoj: hmm, aquamacs

21:40 could that be the problem?

21:40 or, wait

21:40 is that gnu emacs on mac?

21:40 KirinDave: Yes.

21:40 It's not aquamacs

21:40 I wonder if I have slime incorrectly set up.

21:40 tomoj: dunno, then

21:41 there is no set up

21:41 KirinDave: I have to slime-mode every buffer. :\

21:41 tomoj: ah

21:41 KirinDave: That isn't the way it used to be.

21:41 tomoj: right

21:41 I've seen that before

21:41 mysteriously

21:41 don't know now where I've seen it

21:41 or how I fixed it..

21:41 even if I fixed it

21:43 * KirinDave sighs.

21:43 KirinDave: This is why emacs sucks so hard.

21:43 And why any language that depends on it in any way is pretty much doomed to minority status.

22:02 chouser: KirinDave: good thing clojure works great with vim, then. Majority status here we come!

22:02 KirinDave: chouser: Vim is at least as terrible. :\

22:02 chouser: :-D

22:03 moogatronic: ... i spend more time playing with either vim or emacs than I do actually writing code.

22:03 as much as I hate it, eclipse works better for me.

22:04 vim is my rst / python editor of choice for the most part. Getting CCW working in eclipse took me all of 5 minutes... Emacs + anything still not working.. I spent a whole day trying to get vimclojure to work with the nailgun server and just gave up.

22:04 a day == a few hours

22:04 =)

22:05 chouser: I don't use vimclojure/nilgun stuff myself. I'm glad it works for some people, as I am glad people that like IDEs can use them with Clojure.

22:06 I need to be talked into liking eclipse. I'm hoping that happens for me at clojure-conj.

22:06 moogatronic: my problem is that i don't like big bloaty IDE's, but they seem to have the features I like.

22:06 without screwing around forever to get it to work.

22:06 * chouser nods

22:07 moogatronic: i'm only a clojure hobbyist... I get paid to use eclipse and write boring business logic oriented webapps in java/eclipse.

22:08 I would be surprised if anyone talked you into "loving" eclipse... at least appreciating it maybe!

22:08 gowlin: eclipse would be sweet if its text editor wasn't so bad.

22:09 moogatronic: my mission tonight was to find a portable sane way to reduce the glare of the bright white background in eclipse, to little avail.

22:10 f.lux helps a lot actually, other equiv's for other os's...

22:10 grettke: moogatronic: my co-worker loves Eclipse

22:13 moogatronic: grettke: I think for java it's great. Other than i feel that I need a 2560x1600 screen to fully use it. =)

22:13 grettke: moogatronic: lol

22:14 moogatronic: I honestly think I'm using "editors" as a scape goat to prevent myself from fully diving into a non-java/python language.

22:15 grettke: moogatronic: you might like emacs if you like eclipse

22:17 moogatronic: I want to like emacs. I've just had so many years of emacs and vim that it's difficult. I like the philosophy behind emacs.

22:17 but even when configuring my init.el, I find myself using vim to do it.

22:18 meant to say "eclipse and vim'.. =)

22:19 rich_holygoat: heh, I do the same thing -- vim ~/.emacs

22:19 guess I think of Emacs as a programming environment and Vim as a text editor

23:00 scottj: If you want to read more than one thing from a string, is (read-string (str "(" "a 2" ")") ) the way to do it?

23:03 chouser: scottj: that's the easiest way

23:03 scottj: is that lazy?

23:03 chouser: otherwise you need to set up a StringReader, etc.

23:03 ,(class (read-string "(a 2)"))

23:03 clojurebot: clojure.lang.PersistentList

23:03 chouser: nope

23:04 scottj: functions are only lazy if they return a lazyseq?

23:05 chouser: I wouldn't go that far, but a PersistentList is definitely not lazy

23:13 don-cobra: By default, using starter-kit and installing clojure-mode, etc. it looks like clojure 1.0 is installed. What is the easiest way to point to compiled version of master?

23:14 Newbie here trying to get emacs setup w/ latest clojure.

23:32 freakazoid: damn, I made a gist of the relevant section of my .emacs for don-cobra and everything.

23:34 technomancy: mmm... new John Rose blog post.

23:34 brain food... om nom nom.

23:37 http://blogs.sun.com/jrose/entry/larval_objects_in_the_vm

23:38 freakazoid: that dude needs a better picture

23:39 technomancy: he's a JVM superhero; the grainy picture is just there to protect his true identity

23:40 freakazoid: Ohh

23:45 technomancy: is it pretty reasonable to assume a resolution of 1024-786 for conj presentations?

23:46 defn: No offense to Stuart Sierra, but does he not look a lot like Matthew Broderick?

23:48 Also, I am not very familiar with how one might tackle writing to a file with Clojure in two separate processes. My friend is working on a project for a Java class where he has to handle the locking of a file so he can write to it from two different threads. On OSX apparently this works without much work, but on Windows his solution breaks.

23:49 Could anyone offer any possible avenues one might take with Clojure to accomplish something like this?

23:49 I mean I can think of a few -- but I'm curious what other folks would suggest...

23:53 scottj: have an agent and send it messages from the two threads telling it to spit in the file? (I don't know the right answer)

23:58 tomoj: ztellman: ping

23:58 ztellman: tomoj: what's up?

23:58 tomoj: .. (siphon ch broadcaster) (siphon broadcaster ch) .. doesn't this blow the stack?

23:59 on the Channels wiki entry, the multicast example

23:59 ztellman: no, because 'ch' in this case isn't unidirectional, it's one half of a bidirectional endpoint

23:59 tomoj: guess I'm not using it right

23:59 ztellman: did you manage to blow the stack?

23:59 tomoj: yeah

23:59 ztellman: hmm

23:59 tomoj: (def a (channel)) (connection-handler a)

Logging service provided by n01se.net