#clojure log - Dec 21 2010

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

2:19 joshua__: Not enjoying working with C++ at all.

2:19 I'm helping my uncle by writing a bot for a program called CamFrog.

2:19 After just having made a plugin for the sexpbot in this channel.

2:20 Plugin in C++: 20+ files and hundreds of lines of code

2:20 Plugin in Clojure: 1 file

2:21 And I'm not even done yet. Any suggestions as to what database I should be using in C++ for a Windows box? I don't want to spend too much time downloading/getting it set up.

2:22 only need to store a string username and an int total_score (maybe a long but w/e)

2:23 sandGorgon: joshua__, you could look into using sqlite or berkleydb (as embedded) or Postgresql (as full fledged RDBMS)

2:23 Raynes: joshua__: You only need to store two values in total? Why use a database at all?

2:24 amalloy: joshua__: yeah, what Raynes said

2:24 joshua__: Raynes: potentially hundreds of users actually, this program is likely to be very very popular.

2:24 Raynes: If I just had to store two values, I'd just store a Clojure map in a file and read it. Like we do with sexpbot.

2:25 amalloy: joshua__: even with thousands of users there's not much need for a database

2:25 joshua__: People tend to play the current version of the bot, but its closed source and they want to put "mad gab" a game into it.

2:25 Raynes: Right.

2:25 Just a key-value store (a Clojure map) seems like it would be good enough.

2:26 joshua__: I don't think C++ lets you eval a source file actually ;p

2:26 amalloy: Raynes: well, he doesn't have clojure maps in c++, of course. but you can write a string and an int to a file and read it back into c++'s hashmap

2:26 Raynes: amalloy: Well, he should write a Clojure reader of course.

2:26 amalloy: of course

2:26 Raynes: I was working under the pretense that he was going to implement Clojure in C++ as a prerequisite to the project.

2:26 I am disappoint.

2:27 Nonetheless, it still stands. It could be stored as JSON just as well.

2:28 joshua__: Raynes: I think I can handle a text file. I'll try it out. My only worry is that writes would be a big pain.

2:28 amalloy: joshua__: right, i'm with Raynes again, though i'd use xml because json makes me twitch

2:28 Raynes: amalloy: I don't think I know you.

2:28 amalloy: joshua__: not as big a pain as shipping a database engine with your bot :P

2:29 joshua__: amalloy: THAT is why I was so hesitant as to ask.

2:29 joshua__, I was on the mongodb site going.. umm.. do I really want them to have to do this..

2:30 amalloy: joshua__: seriously though, you don't have to write until the bot shuts down, or maybe periodically; and http://jsoncpp.sourceforge.net/ should make it manageable

2:30 (not endorsing this particular parser: just the first google hit)

2:31 joshua__: 28 thumbs up in a stack overflow post so I guess I'll try it.

2:32 btw Raynes, your bot is way more impressive now than it was before. You don't really appreciate how easy it is to make something until it becomes very hard.

2:33 Thank you for not naming "recieve a message" 0x02

2:33 etc

2:33 Raynes: Hah! :>

3:00 joshua__: amalloy, just realized there is an xml library already in the source tree so I'm abandonning the idea of using json

3:00 midnight, give me a break =(

3:00 amalloy: Raynes: score one for amalloy

3:00 joshua__: at least I spotted it eventually

3:25 zmyrgel: I'm trying to find out how to profile my code

3:25 I have a function test in one of my clj files which I want to test, it uses functions from other files

3:27 in my lein project dir I can see the file game$test.class under classes dir but how to get java's -Xprof to run it so I could get the profiler output?

3:30 one issue fixed with -cp project-0.1-standalone.jar but now I get understandable message, Main Method not found in game$test

3:32 should I just modify the code so I call my test function from projects main funtion is there a better way for it?

5:30 kensho: Hi. I'm looking into submitting the clojure contributor agreement. Is there a way to send the clojure contributor agreement via fax?

6:01 AWizzArd: kensho: I already asked a few times. Currently it is not an option to email/fax it.

6:01 Musste mit der Post schicken ;)

6:02 kensho: AWizzArd: I see thanks. Ich hoffe nur die Post verbockt es nicht :)

8:44 AWizzArd: Is instance? the right fn to find out if an object implements a specific Interface or Protocol?

8:45 cemerick: AWizzArd: instance? is right for interfaces, satisfies? is right for protocols

8:48 AWizzArd: Ah good.

8:48 Thanks!

8:48 cemerick: Would you in general prefer Protocols over definterface?

8:49 If you want to extend your Records with some fns.

8:49 (or deftypes)

8:50 cemerick: I very rarely use definterface.

8:50 susumu: hi, I'm getting out of memory errors... I know where, but don't understand why. I've narrowed it down to these two examples:

8:50 (def not_out_of_mem

8:50 (let [result 0]

8:50 (reduce + result (range 50000000))))

8:50 (def out_of_mem

8:50 (reduce + 0 (range 50000000)))

8:51 cemerick: That doesn't mean it doesn't have utility vs. protocols, just that my use cases tend to favor protocols.

8:51 susumu: (println out_of_mem2) blows the java heap every time.

8:52 chouser: susumu: surely you don't have to print it to cause it to blow the heap?

8:52 susumu: something to do with (let result) allowing a local optimize?

8:52 sorry, last line should have been: (println out_of_mem)

8:53 chouser: true, don't have to print it.

8:53 AWizzArd: cemerick: are definterfaces possibly more efficient? Do they allow type-hints that defprotocols don't?

8:54 dnolen: AWizzArd: because of that they are also more tedious. They don't create functions and you have type-hint to avoid reflection.

8:54 chouser: susumu: that's really interesting.

8:54 susumu: first version, not_out_of_mem, doesn't cause out of memory errors.

8:54 chouser: I wonder if it's some kind of regression.

8:54 (reduce + 0 (range 50000000)) by itself also doesn't blow the heap

8:54 dnolen: AWizzArd: I found myself using them a lot more during the :static days, because protocols and :static did not play well together.

8:55 susumu: chouser: regression?

8:55 chouser: I mean, I wonder if this worked correctly in some (older) versions of Clojure.

8:56 AWizzArd: dnolen: which is more tedious? a) definterface or b) defprotocol?

8:56 dnolen: AWizzArd: definterface

8:56 AWizzArd: dnolen: what advantage does definterface over defprotocol?

8:56 Can definterface type-hint more? Is it more efficient, because it can decide at compile-time what to do?

8:56 susumu: same behavior in clojure 1.1.0 (just tried it)

8:57 cemerick: AWizzArd: it's true, protocols don't support hinting of the corresponding methods.

8:58 That doesn't have much of anything to do with compile-time though.

8:58 dnolen: AWizzArd: you can provide arguments types to definterface, but you will also have to type hint your method calls and it's arguments when you use it.

8:59 AWizzArd: What I like so far about the definterface: I have a macro that expands into a defn, and it type-hints its return value. And the definterface method also type-hints its return value. This allows me to call (.add (.myInterfaceFN (my-macroed-defn-that-returns-a-record-implementing-the-ITF)) (JButton. "Hi")) without throwing a reflection warning.

9:00 I don't know if I make .getContainer a Protocol fn get-container that I can also specify that get-container always returns a java.awt.Container

9:01 And also have it making use of the typehint that my macro added to my-macroed-defn

9:01 I will try it out :)

9:02 cemerick: AWizzArd: protocol fns can be hinted, they just don't pass through to the generated interface.

9:03 chouser: AWizzArd: It looks like you can type hint a protocol fn's return value

9:03 dnolen: cemerick: so it's just for documentation purposes?

9:03 cemerick: dnolen: no, the hint is as effective as hinting a regular fn w.r.t. avoiding reflection on return values

9:03 dnolen: whenever I tried type-hinting protocols it seemed to cause me trouble.

9:03 chouser: such that when you call the fn, the compiler will know the return type and method calls on it should be able to avoid reflection with less manual hinting

9:04 dnolen: cemerick: oh, sorry I see type-hinting the *return* value.

9:04 cemerick: right

9:04 chouser: susumu: I'm pretty well stumped

9:04 cemerick: It's all Object in and out of the protocol's generated interface's methods, but that has no bearing on the hints on the protocol's fns.

9:05 susumu: chouser: me too... going to post on google groups

9:05 AWizzArd: Hmm yes, it works so far.

9:05 chouser: susumu: My next thoughts are to examine the bytecode generated by 'def' and/or profile the running code. Both rather intimidating.

9:06 AWizzArd: I said (defprotocol my-proto (^java.awt.Component get-container [this]))

9:07 dnolen: chouser: interesting 1.3.0 doesn't exhibit that issue.

9:07 alpha4 anyway

9:13 chouser: dnolen: really!? I'm seeing it.

9:14 oh, maybe not alpha4

9:16 I'm seeing it on Clojure 1.3.0-alpha4

9:16 strangest to me is that (def x <reduce>) breaks but <reduce> works fine

9:16 dnolen: chouser: oh sorry, I was actually using SNAPSHOT

9:18 actually I'm perhaps I'm not seeing it because my JVM settings are -Xms1024M -Xmx2048M

9:18 chouser: I'm running with -Xmx2m

9:19 ohhhh

9:19 cemerick: you mean 2g?

9:19 chouser: no

9:20 for OOM tests like this, you don't have to wait as long for failure if you keep a small heap

9:20 I bet this is a protocol caching thing

9:20 cemerick: I wouldn't have even thought one could get a REPL with 2m.

9:21 chouser: bah. nevermind. spoke too soon

9:21 (def out_of_mem (last (range 50000000))) fails, no protocol in sight

9:22 (def ok (let [] (last (range 50000000)))) works fine

9:22 dnolen: chouser: yeah, when I run (def x (reduce + 0 (range 50000000)), my memory explodes to ~1.35gb of RAM

9:24 isn't this just explicit head holding? (i.e. something that locals clearing can't handle?)

9:24 mduerksen: chouser, susumu: i don't know the internals of def, but could it be caused by the fact that (def x (reduce... allocates the memory for the range twice (one for the def, and one for the evaluation of reduce). in contrast, a (reduce... alone just allocates it once, and also the (def x (let [] (reduce ... , since within the let, no var is created

9:25 dnolen: hmm, perhaps not, (def x (map inc (range 50000000))) is instantaneous

9:25 chouser: dnolen: lazy

9:25 dnolen: chouser: I know

9:25 chouser: oh

9:25 dnolen: I thought reduce was too.

9:25 chouser: no

9:25 reduce is eager

9:35 AWizzArd: This is odd. I now added a non-hinted protocol fn and that too doesn't produce a reflection warning.

9:35 Is there some kind of type-inference at work?

9:38 dnolen: you don't need hinting for the first argument of protocol. Also if you return a type/record as the first arg to a protocol fn for that same type you also don't need hinting.

9:38 AWizzArd: big benefit of protocols, no type-hinting full speed ahead.

9:39 AWizzArd: dnolen: yeah, though I combined this with a Swing method call.

9:39 (.add my-frame (get-container2 (create-some-panel)))

9:40 create-some-panel returns a (record) MyPanel instance. MyPanel implements a protocol fn get-container2 which is not type-hinted.

9:40 So (.add ^Object x) <-- should throw a reflection warning.

9:40 forgot the my-frame

9:40 (.add my-frame ^Object x) is what the compiler sees

9:41 because get-container2 isn't type-hinted

9:41 chouser: AWizzArd: my-frame is a javax.swing.JFrame?

9:43 bartj: what does it mean when I see a: "call to sadd can't be resolved" reflection warning

9:43 and how would I go about fixing it?

9:43 where sadd is a function call from j-redis

9:44 chouser: bartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.

9:44 clojurebot: You don't have to tell me twice.

9:44 bartj: it's syntax is as follows: (.sadd client param1 param2)

9:44 jcromartie: Does anybody know if it's possible to do something like Seaside in Clojure, without continuations?

9:44 AWizzArd: chouser: yes

9:45 bartj: chouser, I am trying to improve performance by removing the reflection warnings

9:45 AWizzArd: chouser: I just tried another example and there I get a type-hint warning as expected.

9:45 So in general there is no type-inference mechanism. But for this one odd case I am not getting a warning.

9:46 chouser: AWizzArd: you're sure the protocol function doesn't know it's return type?

9:46 AWizzArd: (:tag (meta #'get-container2))

9:46 AWizzArd: chouser: One protocol fn is (^java.awt.Component get-container [this]) and the other is (get-container2 [this]). This is in the concrete implementation of my Record.

9:47 chouser: the call of :tag returns nil.

9:47 for get-container it returns java.awt.Component

9:47 chouser: bartj: ok, in that case you have to tell Clojure at least what class client is, and depending on the sadd methods available, perhaps the classes for param1 and param2 as well.

9:48 AWizzArd: hmph

9:48 AWizzArd: puzzeling

9:48 chouser: bartj: one way to do that is (.sadd ^ClientClass client param1 param2)

9:49 bartj: though you can hint client when you define it instead

9:49 AWizzArd: It really seems to me that for some cases there is an implicit type-inference at work. Maybe something in the JVM, not in Clojure.

9:50 But anyway: I *can* explicitly type-hint the return values of my protocol fns, so it delivers what I am asking for. So, from that pov I won't need definterface.

9:51 But: can defprotocol do primitive type-hinting of function parameters?

9:51 bartj: chouser, thanks!, would I also need to type-hint "sadd"

9:52 cemerick: AWizzArd: no, but that's generally irrelevant

9:52 AWizzArd: Ok, so that is the domain of definterface then.

9:52 This is might be the single one advantage of definterface over defprotocol.

9:52 Or are there others?

9:52 chouser: bartj: the word ".sadd" itself? no. Only its arguments (client, param1, param2, etc.) would ever need to be hinted

9:53 AWizzArd: Well, one thing that I notice is: my protocol fns inherit the namespace of my lib. So, users need to ns/get-container wheras the definterface method can be called (.getContainer rec) everywhere :)

9:54 bartj: chouser, why would you not want to type-hint "sadd" itself?

9:54 AWizzArd: chouser: why did you suggest to not type-hint unless one knows there is a performance hit?

9:55 bartj: chouser, "sadd" returns a type Java Map so, I was expecting to give (^Map .sadd ^Clientclass client...)

9:58 chouser: AWizzArd: why else would you clutter your code with them?

9:59 AWizzArd: chouser: yes, for performance reasons. Though it is in principle dependend on your editor, which could hide the type-hints.

9:59 technomancy: The swank-clojure I currently use is compatible with Clojure 1.3 Alpha 2. Is there already a version which runs 1.3.3a or even 1.3.4a?

10:00 chouser: In 1.3.3a the new thing was manually definde bindable vars. What changed in 1.3.4a?

10:00 chouser: bartj: java methods can't be overloaded on only their return type, so if you hint the args sufficiently, Clojure will know the return type and can use that knowledge in subsequent expressions

10:01 bartj: chouser, that is very informative, thanks

10:01 chouser: AWizzArd: normalized unchecked-* fn names; added *unchecked-math* support; fixes to binding conveyance (and *agent*)

10:01 AWizzArd: hmm

10:01 Do you have an example what "normalizeq" means in this context?

10:02 chouser: AWizzArd: https://github.com/clojure/clojure/commit/3e644c768b1f769217ecd484c019580384c7a670

10:03 AWizzArd: thx

10:04 oh interesting, the options map of defn accepts an :inline

10:05 And I see that :static is still used. I thougt this was removed?

10:08 chouser: :inline is old. Useful, but an undocumented implementation detail that could go away at any time.

10:08 I believe :static is currently ignored, though as you note it is still attached to some core functions.

10:10 AWizzArd: Yes, :static is still present in several functions.

10:10 And :inline is also used here and there, also rhickey recently added some of them.

10:10 For example at https://github.com/clojure/clojure/commit/eb076dab7b7be68957922f47ad8d140e4ec579a1

10:10 chouser: yes. I enjoy exploiting :inline, but it's a dangerous game.

10:10 AWizzArd: ;)

10:11 chouser: it allows you to create dual-nature vars, that act as macros or functions depending on how they're used

10:11 AWizzArd: Yes. We both discussed this some weeks ago.

10:11 chouser: ok

10:12 AWizzArd: I found this interesting.

10:12 Anybody here who successfuly runs swank-clojure with Clojure 1.3.4alpha?

10:16 bartj: I see a bunch of reflection warnings in clojure/contrib/pprint/pretty_writer.clj

10:16 but, I do not seem to have imported the clojure.contrib.pprint anywhere

10:32 mduerksen: chouser, susumu: any new insights regarding the heap-overflow issue?

10:35 chouser: nope

10:56 tonyl: hello

11:08 AWizzArd: Hi tonyl.

11:10 * tonyl is looking for an audiobook of the SCIP book, that is a long shot

11:32 fhd: Hi. It seems I cannot "use" records created via defrecord in other namespaces (i.e. (MyRecord. foo bar)) - Is there a way to make them public?

11:34 chouser: fhd: you either need to import the class MyRecord by using 'import', or have a factory function in that other namespace, like (defn my-record ...)

11:34 fhd: chouser: Ah, thanks

11:35 AWizzArd: Btw, I suggested rhickey to not implement those factories automatically, but instead wait and see how Records will be used. I think we gathered a good bit of experience and have use cases and it should now be possible to add some factories.

11:37 leif-p: Hi, all. Is anyone present familiar with the labrepl exercises from Relevance?

11:38 fhd: leif-p: I've done a few.

11:42 leif-p: I was doing the 'zero-sum' exercise, and as is common with exercises, the most interesting ones don't have solutions given. I don't really have any experience with concurrent programming, so I wanted to ask someone if my reasoning about the Bonus question 1 was correct.

11:42 fhd: leif-p: Sorry, didn't get that far :(

11:45 leif-p: fhd: Ah, well, thanks anyway. Anyone want to field a basic concurrency question?

11:47 tonyl: I would say just shoot the question and somebody would pick it up

11:48 ~anyone

11:48 clojurebot: Please do not ask if anyone uses, knows, is good with, can help you with <some program or library>. Instead, ask your real question and someone will answer if they can help.

11:59 leif-p: OK, let's say you have a set of 'bank accounts' repr. by {id (ref balance), ...} OR (ref {id balance, ...}). You have to transfer between accounts without changing the total, and you have to be able to read a consistent total. The question says "One of these approaches is the correct one. Which one, and why? Under what circumstances would the other approach make sense?" My reasoning is that transfers will be a lot more co

12:11 AWizzArd: I have a seq and want to fetch the element that follows a given keyword. Do you have other ideas than this to fetch the 1000?

12:11 ,(let [[_ n] (drop-while #(not (#{:key} %)) [1 2 3 4 5 :key 1000 6 7 8])] n)

12:11 clojurebot: 1000

12:11 AWizzArd: (drop-while #(not (#{:key} %) coll) <-- better solution?

12:23 leif-p: AWizzArd: The second is just a step of your first solution, right?

12:27 AWizzArd: Oops, sorry, you were asking "is there a better solution?" Nevermind.

12:28 AWizzArd: Yes. The line I started with (drop-while ...) is what I currently have.

12:31 tonyl: I think that is a very concise way to do it, but I am not an expert. I can't think of any other idea than drop-while

12:33 maybe reduce, but that won't stop processing when it finds :key

12:34 leif-p: AWizzArd: I agree with tonyl. Though if you don't need to recognize several keys I think #(not= :key %) reads better. And I would use 'second' instead of the 'let'.

12:35 tonyl: maybe ##(drop-while (complement #{:key}) [1 2 3 4 5 :key 1000 6 7 8])

12:35 sexpbot: ⟹ (:key 1000 6 7 8)

12:35 tonyl: then use second like leif-p says

12:36 &(second (drop-while (complement #{:key}) [1 2 3 4 5 :key 1000 6 7 8]))

12:36 sexpbot: ⟹ 1000

12:39 amalloy: leif-p: re banking, i think you want (ref {id balance}) from those two choices, but i'm always a big proponent of (atom {id1 bal1, id2 bal2})

12:43 but tbh i don't think it makes much of a difference whether you ref just the balance or the pair; in both cases your amount-totalling thread will have to (ensure x) for every ref x in the map

12:48 leif-p: It seems similar to table vs. row locking in databases, but I don't know if that analogy holds.

12:49 amalloy: leif-p: i think it's similar to row vs column locking :P

12:49 you have to wrap the whole thing in an atom/ref to get actual table locking

12:53 leif-p: amalloy: Let me rewrite it so I know we're talking about the same thing: {id1 (ref balance1), id2 (ref balance2), ...} OR (ref {id1 balance1, id2 balance2, ...} ) <-- whole thing wrapped

12:54 amalloy: right

12:54 though once you only have one ref it might as well be an atom

12:57 AWizzArd: tonyl and leif-p: thanks for your input.

12:58 leif-p: amalloy: So is my reasoning above correct, or am I misunderstanding refs?

12:58 AWizzArd: np

12:58 cemerick: I suggest that the main Clojure mailing list be put back on full moderation for a spell.

12:58 amalloy: leif-p: what reasoning? the row-vs-column thing? or do you mean the really long message you tried to send that got clipped?

12:58 * cemerick is almost serious

13:00 amalloy: cemerick: i haven't been following. has the Ah-ha thread gotten bad too?

13:00 cemerick: amalloy: there's any number of bad threads. The s/n ratio has completely flipped around AFAICT.

13:00 Maybe I have that impression because I only look when people send me mails/tweets/etc saying "whoa, what's up with the ML"?

13:01 amalloy: cemerick: bizarre. are there enough people around who can be "trusted" to moderate without flipping out? cause it seems like even pillars of the community are getting involved in some of these threads

13:02 cemerick: amalloy: only in a palliative capacity, unless I've missed something.

13:03 amalloy: cemerick: wow, it's pretty rare that irc makes me look up a word

13:03 $dict palliative

13:03 sexpbot: amalloy: adjective: Serving to palliate; serving to extenuate, mitigate, or alleviate.

13:04 cemerick: I think OS X's definition is more apt: "relieving pain or alleviating a problem without dealing with the underlying cause"

13:04 amalloy: ah

13:04 leif-p: amalloy: I was not aware; my client never truncates/warns me. Here's my question: http://pastebin.com/T24s8x7H

13:05 cemerick: There was an item on HN a week or two ago about how egalitarian communities die with the influx of less engaged / more foolish members. Anyone have the link for that on hand? My google-fu fails me.

13:06 technomancy: cemerick: kinda feels to me like being in university when a bunch of freshmen flood in, all wowed by this one prof.

13:07 cemerick: technomancy: I think that's putting it too lightly.

13:07 amalloy: leif-p: oh, i misread what the second approach was, the first time

13:07 the second approach was indeed exactly what i suggested

13:10 the first approach is definitely wrong, and the second right. your reasoning about "two accounts in a transaction" is true, but is misguided; the problem is i'm having trouble quantifying where the wrong-thinking is. i think it's related to immutability, and the cheap-ness of @foo. do you have The Joy of Clojure?

13:12 AWizzArd: technomancy: The swank-clojure I currently use is compatible with Clojure 1.3 Alpha 2. Is there already a version which runs 1.3.3a or even 1.3.4a?

13:13 amalloy: a good general rule, though: you usually want as few reference-type objects as possible; making them bigger is a much smaller problem than making more of them

13:15 leif-p: ^^

13:18 leif-p: amalloy: I do not have tJoC. I was worried that if I use accounts = (ref {}), and I have 1000 people trying to do (transfer accounts from to amount), there's going to be a lot of waiting around.

13:20 amalloy: leif-p: that's an interesting point. i guess i haven't had that sort of usage pattern before

13:22 technomancy: AWizzArd: I just got some patches from monsieur stuart s that allegedly improve support for 1.3; lemme push to clojars

13:23 amalloy: leif-p: the problem with your approach (and it is a soluble problem) is that when you do try to verify that the total is 0, you'll need to somehow deref them all in a consistent snapshot. eg (reduce + (map (comp deref key) accounts)) won't work

13:25 i think (reduce + (dosync (map (comp ensure key) accounts))) will work, but it means the whole balance-checking operation will have to reload lots of times because the constant balance-transfers are trampling it

13:29 AWizzArd: technomancy: btw, is there a direct download link from clojars?

13:30 technomancy: AWizzArd: there is somewhere; couldn't tell you off the top of my head

13:31 AWizzArd: http://clojars.org/repo/swank-clojure/swank-clojure/1.3.0-SNAPSHOT/

13:32 leif-p: amalloy: Whoa, I can't just wrap the whole reduce in a dosync to ensure consistency? I have to 'ensure' each and every ref in the dosync?

13:33 amalloy: leif-p: right, because imagine the alternative. you're iterating over a bunch of refs, right? so you have to deref them all

13:33 AWizzArd: technomancy: thx

13:34 amalloy: the problem is that @foo, even in a ref, is an instant snapshot of foo's current value; only *writing* to a ref (or ensuring it, which is basically a dummy write) will ever make a transaction retry

13:36 refs are not locks

13:41 leif-p: amalloy: Erk. The labrepl ex. has the (dosync (reduce + ...) code I described, and it says "change total-balance to read within a transaction, which guarantees that all reads are from the same point-in-time." So that's wrong?

13:43 amalloy: leif-p: well, it's possible that what's wrong is me. i'm pretty sure this is why ensure exists, though

13:48 leif-p: hm. interesting. i guess i'm wrong

13:48 well, now i wonder what ensure is for

13:49 leif-p: anyway, thanks for showing me this. hopefully we've both gotten a better understanding of refs

13:54 leif-p: amalloy: Thanks for all your help. Since you and the exercise differ, I'll just have to ask again when someone from Relevance (or rhickey :)) is around to see if they can clarify.

13:57 amalloy: leif-p: https://gist.github.com/9313060b4a54377cdd67 is a quick test case i wrote that you can play with

13:59 bartj: , (remove #(contains? ["a" "b" "c"] %) ["a" "b" "c" "d" "e" "f"])

13:59 clojurebot: ("a" "b" "c" "d" "e" "f")

13:59 bartj: I was expecting only "e" and "f" in the above experiment

13:59 technomancy: clojurebot: doc contains?

13:59 clojurebot: contains? is for checking whether a collection has a value for a given key. If you want to find out whether a value exists in a Collection (in linear time!), use the java method .contains

14:02 bartj: technomancy, thank you

14:03 I have about five million items in a collection and I would like to remove 100 of them

14:03 currently I am using a clojure.set/difference

14:03 something like this: (clojure.set/difference (into #{} 5-million-items) (into #{} 100-items))

14:04 I was thinking about using a remove instead, since it is lazy

14:04 leif-p: bartj: (remove #(contains? #{"a" "b" "c"} %) ["a" "b" "c" "d" "e" "f"]) or just (remove #(#{"a" "b" "c"} %) ["a" "b" "c" "d" "e" "f"]) seem to work

14:05 amalloy: leif-p: or indeed ##(remove #{"a" "b" "c"} ["a" "b" "c" "d" "e" "f"])

14:05 sexpbot: ⟹ ("d" "e" "f")

14:05 amalloy: but all of those require putting everything into a set, which bartj seems to be avoiding

14:06 otoh, bartj, you only have to put the 100 items into a set; the 5M can be processed lazily

14:07 bartj: to something like this: (remove #(.contains 100-items %) 5-million)

14:08 leif-p: amalloy: Ah, right you are. But (remove (set 100-items) huge-lazy-seq) can stream over the large data. Which you just said.

14:08 I type too slowly. :)

14:08 amalloy: leif-p: #(foo %) is equivalent to just foo

14:09 bartj: (remove (set 100-items) 5-million)

14:09 bartj: amalloy, you mean taking advantage of the fact that the second collection in a clojure.set/difference can be lazy

14:09 https://groups.google.com/d/topic/clojure/7QVFwtXWAi8/discussion

14:11 amalloy: bartj: no, that is kinda crazy

14:12 stu is 100% right on that one: it's not specified in the docs specifically because it's an implementation detail. it might change at any time, and you should only pass sets into clojure.set/difference

14:19 bartj: amalloy, (a-set element) -> checks for the presence of the element in the set, right?

14:20 similarly, (a-vector element) -> returns vector[element]

14:20 amalloy: bartj: indeed

14:21 technomancy: bartj: if you're asking what the point of the contains? function is now, that means you're on the right track.

14:21 bartj: technomancy, you type fast!

14:22 amalloy: bartj: it's the keyboard pants

14:22 bartj: amalloy, shirt pant?

14:24 In any case, huge thanks to all

14:29 cemerick: There are plenty of collection implementations that aren't also IFns…

14:30 bartj, technomancy ^^

14:31 fogus`: http://fogus.me/fun/marginalia/ :-)

14:32 bartj: cemerick, like sequences ?

14:32 technomancy: cemerick: I didn't say there wasn't a good answer =)

14:32 bartj: , ('(1 2 3) 1)

14:32 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn

14:34 cemerick: bartj: and tons of other data structures that can be trivially integrated into clojure idioms like contains? (but not more complicated implementation details like IFn, etc)

14:44 brehaut: fogus: perhaps you could use a minified version of syntax highligher if you are embeding it in every marginalia output?

14:45 * chouser wonders how many lines of Java code are in a ton

14:45 crowbar71: 2000 lines?

14:45 :p

14:46 brehaut: chouser: surely its language independant?

14:46 chouser: I think a line of Clojure probably weighs more than a line of Java

14:49 Crowb4r: yeah if it's C++ a ton of coe is just writing the memory managment on a small C++ program. :p

14:49 * amalloy agrees with chouser here

14:49 Crowb4r: s/coe/code/

14:49 sexpbot: <Crowb4r> yeah if it's C++ a ton of code is just writing the memory managment on a small C++ program. :p

14:50 Crowb4r: ohh nice feature. ;)

14:50 thought I was just being crafty.

14:51 amalloy: $sed -Crowb4r s/crafty/devious/

14:51 sexpbot: <Crowb4r> thought I was just being devious.

14:52 Crowb4r: ohh that is super nice.

14:52 * Crowb4r finds sexpbot's code

14:52 amalloy: Crowb4r: glad you like it!

14:53 Crowb4r: you write him/her?

14:53 amalloy: Raynes mostly; the past couple months i've been working a lot on it too

14:54 dnolen: fogus`: marginalia is cool!

14:54 Crowb4r: ahh, using the pirc framework for JAVA or roll your own?

14:54 dnolen: fogus`: I'm getting a lot of extra scrollbars in Safari tho.

14:54 amalloy: he started from pirc and then rolled his own

14:54 fogus`: dnolen: Thanks. Yeah, it needs more work.

14:54 amalloy: and this weekend i wrote https://github.com/Raynes/sexpbot/wiki/Plugin-quick-start-guide as well as a big update to the README, if you're interested in contributing

14:55 Crowb4r: I may look into that. I use pirc myself. is the one you guys made faster then pirc?

14:55 or just more idiomatic?

14:55 fogus`: brehaut: Thanks. That is a good idea.

14:57 amalloy: Crowb4r: no idea. i haven't looked at the internals

14:57 Crowb4r: ahh ok

14:57 I should toss Perrin on github and have you look at him.

14:57 amalloy: but it's at http://github.com/Raynes/irclj, i think, if you want to look

14:59 Crowb4r: I have a forecast feature and a last.fm feature as well.

14:59 amalloy: $seen LauJensen

14:59 sexpbot: LauJensen was last seen talking on #clojureql 1 minute and 42 seconds ago.

15:00 dnolen: fogus`: .syntaxhighlighter { ... overflow: visible !important; ... }, should fix it

15:00 amalloy: Crowb4r: damn. i was hoping to find someone who hadn't been hard from for a while

15:00 dnolen: not sure why there are so many !important styles. I hate !important

15:00 fogus`: dnolen: Thank you sir

15:00 chouser: $seen rhickey

15:00 sexpbot: rhickey was last seen quitting 2 weeks and 1 day ago.

15:00 Crowb4r: amalloy: huh? hard from for?

15:01 amalloy: heard

15:01 arkh: Is there an easier way to add a local jar to leiningen's classpath than changing things in ~/.m2 and working with Maven (hoping to avoid maven here)

15:02 raek: arkh: lein install?

15:03 arkh: raek: I'll read the docs on that - thank you

15:06 cemerick: The miserable pile that is iterators and enumerations makes me wish black death upon those responsible.

15:06 *serenity now*

15:07 * cemerick goes back to his usual cheery self

15:07 amalloy: cemerick: java.util.Enumeration, or java.lang.Enum?

15:07 cemerick: The former, plus Collections/enumeration, and the whole lot that hangs with them.

15:07 livingston: I haven't used spit much (I'm assuming that's the preferred way to write out a list), I'm calling (spit "file" *foo*) where *foo* is a (def *foo* (some list thing)) I keep seeing only clojure.lang.LazySeq@6580f481 in my output .. how do I ensure I get the list output?

15:07 amalloy: &(doc spit)

15:07 sexpbot: ⟹ "([f content & options]); Opposite of slurp. Opens f with writer, writes content, then closes f. Options passed to clojure.java.io/writer."

15:08 amalloy: livingston: (spit "file" (doall *foo*)) if the list isn't too long

15:08 chouser: or (split "file" (prn-str *foo*))

15:10 livingston: amalloy: I treid that but the same thing happens but if I just type *foo* at the repl I see what I need

15:11 chouser: that worked -- so what am I missing about the other way? I would assume it would have done what I expected?

15:11 amalloy: livingston: really? doall should force all the lazy seqs. maybe you should post a gist of what you're doing instead of a summary?

15:12 Crowb4r: So what awesome things are going to be in 1.3?

15:12 raek: livingston: spit writes strings to files. you have to make the form you want towrite into a string first

15:12 livingston: (spit "file" (pr-str *foo*))

15:12 chouser: amalloy: it does force it, the problem is .toString on a lazy seq always just prints the object id

15:12 raek: amalloy: even though the lazy seq is forced, it's still a lazy seq

15:12 chouser: ,(str (lazy-seq '(1 2 3 4)))

15:12 clojurebot: "clojure.lang.LazySeq@e93c3"

15:13 raek: spit only calls str/.toString on the argument

15:13 ,(pr-str (lazy-seq '(1 2 3 4)))

15:13 livingston: ah I see - ok that makes more sense

15:13 clojurebot: "(1 2 3 4)"

15:13 Crowb4r: wouldn't apply str work as well?

15:13 chouser: if you want readable output, you want pr, prn, pr-str, or prn-str

15:13 raek: Crowb4r: for one level, I suppose so

15:13 Crowb4r: ,(apply str (lazy-seq '(1 2 3 4)))

15:13 clojurebot: "1234"

15:14 raek: hrm, yeah...

15:14 nevermind

15:14 Crowb4r: not saying it's a good idea at all.

15:14 livingston: ok so in parallel, slurp brings in only a string too, right? what's the best way to turn that back to a list?

15:15 raek: livingston: read-string

15:15 (btw, why isn't that called "read-str"?)

15:17 amalloy: raek: i think it's because in pr-str pr is an abbreviation so we shorten str to match

15:17 livingston: perfect... thanks (I miss lisp read etc.) that worked though

15:17 amalloy: livingston: read-string *is* lisp read

15:17 tonyl: there is still read for data structures, not strings

15:18 livingston: except I have to bring the string in first, right? I can't call read read off the open file?

15:18 oh nice there is just read ok.

15:18 amalloy: &(with-in-str "(foo blah a list)" (read))

15:18 chouser: read itself works on a stream, but read-string is easier to use when it's sufficient.

15:18 sexpbot: ⟹ (foo blah a list)

15:19 amalloy: livingston: read-string just expands into the above

15:19 livingston: it's a big string, I'd rather not bring it in twice.

15:19 Crowb4r: Is ther ea concise feature list for 1.3 anyplace?

15:20 amalloy: livingston: right. so (with-in-str (slurp file) (read) (read) (read)...)

15:20 chouser: Crowb4r: http://groups.google.com/group/clojure/msg/24c7696808bddfc7

15:22 Crowb4r: Thank you

15:23 livingston: why not (read (reader "file")) ? (alhtough I can't seem to find reader right now)

15:23 chouser: clojure.java.io/reade

15:23 amalloy: livingston: if you bound the reader and reused it, that would work too

15:24 chouser: (with-open [r (reader "file")] (read r))

15:24 but note that read only reads one form. if you need more than that, you need to handle more complexity

15:24 livingston: alhtough java.io.BufferedReader cannot be cast to java.io.PushbackReader so I guess I need the with-open too makes sense... that's a little more what I'm used to

15:24 fogus`: dnolen: Fixed. Thanks again.

15:25 hiredman: if only there was a function that would repeatedly call other functions

15:25 devinus: ok...when did clojure-contrib become such a pain to compile?

15:25 livingston: (I'm sorry it's really hard to type and read my web client is freaking out and doing some strobe refresh thing I might have to restart this)

15:25 hiredman: when ss got his paws on the build

15:25 Crowb4r: SS?

15:25 clojurebot: I guess that is my answer.

15:25 dnolen: fogus`: nice

15:25 tonyl: trampoline, maybe?

15:25 raek: livingston: with-open doesn't turn a BufferedReader into a PushbackReader. you'd have to do something like (PushbackReader. (reader ...))

15:27 hiredman: stuart sierra

15:28 devinus: modules/def/src/main/clojure/clojure/contrib/def.clj

15:28 is that truly necessary?

15:29 * devinus shakes head.

15:29 chouser: devinus: I sympathize. On the other hand, in what way does that hurt you?

15:29 devinus: chouser: hurt? i wouldn't say hurt, other than i just had to click seven times to open up to the actual file

15:30 * chouser nods

15:30 technomancy: that filename alone it takes up 1/3 of the width of my screen

15:30 well, nearly a third

15:30 devinus: there's like...nothing else in the files leading up to it

15:30 brehaut: devinus: conways law in action?

15:30 technomancy: devinus: java developers are typically paid by the directory.

15:30 devinus: :)

15:30 technomancy: :P

15:30 Crowb4r: technomancy: LOL

15:31 dnolen: devinus: another victim of mavenization

15:31 amalloy: technomancy: it takes up almost half of my screen; directories like that are no good for the visually-impaired

15:32 technomancy: we used maven-style paths for like six months on my project at work, and everyone breathed a huge sigh of relief when we switched away

15:32 devinus: amalloy: are you saying clojure hates blind people?

15:32 technomancy: including the people who suggested them in the first place

15:32 devinus: :O

15:33 chouser: technomancy: maven-style paths but without maven?

15:33 technomancy: chouser: we were on maven for quite some time

15:34 devinus: ok, clojure question

15:34 technomancy: 9 months or so

15:34 devinus: does clojure have a condition/restart system like CL?

15:34 tonyl: technomancy: what style do you use now?

15:34 technomancy: tonyl: src/foo/bar.clj

15:34 chouser: devinus: there is error-kit in contrib. Do you have a need for actual restarts?

15:35 technomancy: where do you put your java and antlr files?

15:35 devinus: chouser: maybe not yet, but i was curious

15:35 chouser: and your .css, .js, and .html?

15:35 devinus: ah, good. that's roughly the spirit in which it was written

15:35 technomancy: chouser: it's not a web app, but HTML and the like would go in resources/

15:36 chouser: I think maybe one or two people on our team know Java, but there's no chance it would ever get introduced to this codebase

15:36 chouser: technomancy: there will never be anything in src except clojure code?

15:37 brehaut: argh. hacker news must be the best advertisment for not doing a continuation based web framework. im sure i click a couple of expired linsk every day

15:37 technomancy: chouser: there are some JS files for mapreduce jobs; they live in src/ like anything else

15:37 that's why the filenames end in .js.

15:37 * chouser nods

15:40 cemerick: Just out of curiosity, who's typing project-relative paths at all?

15:41 bartj: why would a call to a map function give a Stack Overflow?

15:41 since map was lazy, I thought this was impossible

15:41 chouser: src/main/clojure vs. src/ isn't as big a loss for our project as com/company/project/namespace.clj vs. namespace.clj, but that change went down long ago with much less fuss.

15:41 brehaut: bartj: the function map calls is still able to stack overflow

15:41 chouser: when forced

15:42 cemerick: chouser: I'd ask the same question re: com/company/project/foo.clj, too. *shrug*

15:42 brehaut: ,(map (fn overflow [a] (overflow a)) [1])

15:42 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>

15:43 chouser: ,(let [c (map (fn overflow [a] (overflow a)) [1])] 5)

15:43 clojurebot: 5

15:43 cemerick: That is, optimizing project layout for directory depth seems like a strange choice in general.

15:44 chouser: cemerick: do you use your mouse while you're programming?

15:44 cemerick: like, is there a shortage of inodes on people's hard drives or something?

15:44 brehaut: chouser: oh yeah true!

15:44 Crowb4r: I use lots of emacs and tab kay. :p

15:44 chouser: brehaut: so depending on how precisely bartj's question was phrased...

15:45 Crowb4r: I'm use to the tab key tanks to python, so hitting tab for autocomplete is not a strech.

15:45 cemerick: chouser: Very rarely.

15:45 Crowb4r: s/tanks/thanks/

15:45 sexpbot: <Crowb4r> I'm use to the tab key thanks to python, so hitting tab for autocomplete is not a strech.

15:45 chouser: cemerick: how do you open a file to edit?

15:46 cemerick: I never click to do that, almost always type the path.

15:46 rata_: hi all

15:46 Crowb4r: he does all his programming on a C64 still. :p

15:46 bartj: the map is extremely simple

15:46 cemerick: chouser: Say the file I want is @ src/main/clojure/com/snowtide/pdf/io.clj -- Cmd-Shift-R, type "pdf/io", hit return.

15:46 chouser: it's really not a big deal -- having a build system correctly and automatically handle antlr, java, and clojure compilers is a much bigger deal

15:47 bartj: and looks like this: (map #(String. (bytes %) "UTF-8"))))

15:47 chouser: cemerick: cool!

15:47 cemerick: or, "c/s/p/io", if there's lots of ambiguity and I don't want to cursor through a bunch of options, etc.

15:47 Lajla: cemerick, I worship your shadow.

15:48 but only if you give me my new recur

15:48 cemerick: Eclipse's matching in that regard is almost as good as TextMate's in that regard.

15:49 * cemerick shouldn't type here with three other IM conversations ongoing :-(

15:50 bartj: pity is all the errors in the stacktrace show clojure.lang or clojure.core

15:50 nothing in my files

15:50 Crowb4r: Hmm, is there a good place to learn about java bytecode

15:50 http://groups.google.com/group/clojure/msg/24c7696808bddfc7

15:50 opps

15:50 my bad

15:50 chouser: bartj: don't give up. full stack traces are verbose, but almost always have the clues you need

15:51 bartj: if your environment is only printing the final (or only ever the root) cause, figure out how to get around that to the true full stack trace.

15:51 rata_: why (class ((update-in {} [1] conj 2) 1)) is clojure.lang.PersistentList?

15:51 chouser: then paste it somewhere and we'll help

15:51 amalloy: &(class (conj nil 2))

15:51 sexpbot: ⟹ clojure.lang.PersistentList

15:52 chouser: right. that is, conj on nil creates a list

15:53 rata_: mmm.. and why that?

15:54 chouser: what should it create?

15:55 rata_: mmm... I think PersistentList is ok =P

15:55 chouser: :-)

15:55 rata_: I have solved my bug anyway :)

15:56 amalloy: rata_: if you want it to create a vector you can

15:56 &(class ((fnil conj []) nil 2))

15:56 sexpbot: ⟹ clojure.lang.PersistentVector

15:56 rata_: oh thanks =)

15:57 bartj: here is the stack trace - http://pastie.org/1396100

15:57 chouser: It is an interesting question. Since we have come to say that lists are mainly for code and sequential data is more often held in vectors, why shouldn't conj on nil be changed to create vectors?

15:57 rata_: I want a set... and I was doing (update-in m [k1] dissoc k2), but the right thing was (update-in m [k1 k2] #{})

15:57 bartj: There are about five lines referencing clojure.core* and clojure.lang* which repeat ad-infinitum

15:57 rata_: so I don't have nils in my map

15:58 amalloy: chouser: that would reverse the order of conj

15:58 &(conj nil 1 2)

15:58 sexpbot: ⟹ (2 1)

15:58 amalloy: &(conj [] 1 2)

15:58 sexpbot: ⟹ [1 2]

15:59 rata_: sorry, (assoc-in ...)

15:59 amalloy: so it breaks backwards compatibility, possibly badly

15:59 chouser: it would indeed be a breaking change

16:00 Crowb4r: sounds like someting for a version 1.5 or 2.0 then. :p

16:00 amalloy: Crowb4r: no, 1.3 is all about horrible evil breaking changes, if you read the ML. maybe we could add some more

16:01 chouser: bartj: looks like you have a very deeply nested filters

16:01 & (nth (iterate #(filter identity %) [1]) 1000)

16:01 , (nth (iterate #(filter identity %) [1]) 1000)

16:01 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>

16:01 chouser: , (nth (iterate #(filter identity %) [1]) 10)

16:01 clojurebot: (1)

16:02 Crowb4r: amalloy: Oh awesome! Can I get in on these breaking changes!

16:02 I like to break all sorts of things.

16:03 bartj: , (nth (iterate #(remove identity %) [1]) 1000)

16:04 , (nth (iterate #(remove identity %) [1]) 1000)

16:04 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>

16:04 bartj: chouser, it's actually a remove instead of a filter

16:04 chouser: oh, interesting

16:04 amalloy: chouser, bartj: i don't see how remove instead of filter matters

16:04 chouser: ,(nth (iterate #(doall (remove identity %)) [1]) 1000)

16:04 clojurebot: ()

16:05 bartj: (remove (set 100-items) couple-of-million-items)

16:05 chouser: bartj: that should be ok

16:05 note it's the remove-of-a-remove-of-a-remove-etc where all the steps are lazy that is the problem.

16:06 a single lazy remove on a very large seq should be just fine

16:06 or making each step eager

16:06 as I did with doall above

16:06 bartj: chouser, it's the last step in a "loop", so my guess is that it would not be a nested-lazy

16:07 chouser, I could be wrong

16:07 amalloy: bartj: yes it will

16:07 chouser: if you're recuring on the result of a remove, and doing a remove on that, they will nest

16:07 amalloy: (remove foo blah) returns a lazy seq representing a remove, which you then loop on, and layer another remove

16:07 bartj: ah!

16:08 chouser: if you don't actually need the laziness, drop that doall in there and the problem should disappear

16:09 amalloy: or gradually build up a set to use as the remove-predicate, then do one remove at the end

16:10 Crowb4r: geesh, I have been subscribed to the mailing list for about 10 months now and my clojure mail filter has nearly 12k in messages.

16:10 bartj: I thought Clojure tail recursion doesn't use a stack :(

16:10 chouser: bartj: it doesn't

16:10 amalloy: bartj: it doesn't, but that's not relevant

16:11 bartj: then, I am a bit non-plussed regarding the stack overflow

16:11 chouser: bartj: the stack overflows when you try to realize deeply nested lazy-seq-producers

16:12 amalloy: bartj: *you* are using a stack, by layering N lazy filters on top of each other

16:12 bartj: hmm, ok

16:12 amalloy: then, when your loop/recur is finally done building this huge list of things to do, you realize the sequence all at once

16:12 which involves burrowing through the whole stack you made

16:12 chouser: in order to get the first item in (remove f s1), remove must force at least one step of s1

16:13 if s1 is itself (remove f s2), then s2 must be forced, etc.

16:13 so a single (first s0) can potentially cause a deep stack to be created trying to find an actual item that none of the layered removes is going to filter out

16:15 bartj: amalloy, I thought we were being clever using (remove (set 100-set) million-items) in a loop

16:15 but, I guess I was wrong, after all

16:16 chouser: that part is ok. it's only a problem if million-items is actually a lazy seq on a lazy seq on a lazy seq...

16:17 bartj: chouser, hmm, ok; would you say Clojure is ill-suited for this task of

16:17 removing a small number of items from a very large set; until the large set is empty

16:18 chouser: no, I wouldn't say that. I would say that as you push limits of the JVM (stack size, heap size, etc.) it's important to understand the implications of what you're actually doing when designing your solution.

16:20 I couldn't recommend a different solution without understanding better what you're trying to do

16:20 amalloy: chouser: right. so far the best solution for bartj's task is (let [million-items []]) - just empty the large list :)

16:21 chouser: heh

16:23 bartj: are you trying to discover the minimal set that includes all items from your million-items?

16:23 bartj: chouser, no

16:24 I have a million-items and after each iteration about 20-50 of them get deleted/removed

16:25 amalloy: bartj: the question is, what are you actually doing that causes you to want to remove 50 elements in each step. then maybe chouser (or i?) can point out a better algorithm

16:25 bartj: I need to remove these 20-50 items from the million-items until there are no items in the million items

16:25 chouser: so in the end, each item in have to be compared against every one of the 20-50 for every iteration until it is found

16:27 bartj: well, yes

16:27 amalloy: then perhaps you want a lazy-seq of all the 20-50 sets, and then map once over your million-items to see which of those lazy-seqs it matches first

16:28 chouser: ok, then simply wrapping your (remove ...) so that it's (doall (remove ...)) will solve the stack overflow and not cause any more total computation than what you would have to do anyway

16:29 bartj: chouser, yes, but I still find that really slow

16:29 Crowb4r: So who exactly are the mainline devs on clojure?

16:30 chouser: well, that's new question then

16:30 bartj: I am trying to do a doall after say 20 iterations or x iterations

16:30 chouser: bartj: I doubt that'll be faster

16:30 bartj: but, I am not sure if it would entirely help

16:32 amalloy: chouser: does my proposal make sense? i'm not sure, myself

16:32 chouser: amalloy: seems vaguely plausible, given what we know of the problem.

16:33 bartj: where are these 20-50 item batches coming from?

16:34 bartj: ok I'll come clean and explain the full problem

16:34 I have a list of a million songs and I am deduping them based on some fingerprint

16:35 where a fingerprint uniquely identifies the song

16:35 there will be a couple of fingerprints/songs that are the exact copies of each other

16:35 and hence will be removed in the next iteration

16:36 so hence I have this:

16:38 (loop [f fingerprints] 1. remove duplicates of "f" 2. get new set of fingerprints (ie. fingerprints - "f") 3. recur with the new set of fingerprints

16:38 chouser, the 20-50 item batches are the duplicates in the above explaination

16:38 chouser: so you will eventually have to fingerprint every song

16:38 bartj: yes

16:40 chouser: ,(let [songs (repeatedly 1000 #(rand-int 1e8)), fingerpseq (map #(rem % 10) songs), fingerpset (zipmap fingerpseq songs)] (vals fingerpset))

16:40 clojurebot: (82365500 36210571 29167172 10757843 66017534 81361065 90174516 12131347 14368608 22495869)

16:41 devn: :)

16:41 chouser: s/fingerpset/fingerpmap/

16:41 sexpbot: <chouser> ,(let [songs (repeatedly 1000 #(rand-int 1e8)), fingerpseq (map #(rem % 10) songs), fingerpmap (zipmap fingerpseq songs)] (vals fingerpmap))

16:42 chouser: that will lazily fingerprint each song, building a map of each fingerprint to exactly one song, returning a seq of one song per fingerprint

16:43 bartj: hmm, ok

16:43 the main point is that I would be needing to efficiently remove the fingerprints in each iteration?

16:43 chouser: where songs are represented by random numbers, using their last digit as the fingerprint

16:43 amalloy: chouser: the zipmap ruins all the laziness, doesn't it?

16:44 i guess you have to do that anyway

16:44 chouser: amalloy: the zipmap causes the full list of unique songs and fingerprints to be held in memory in the end. I don't see any way around that really.

16:45 but the laziness means duplicate songs and fingerprints are not kept, for whatever that's worth.

16:45 amalloy: right

16:45 chouser: bartj: I don't yet see the value in doing "batches" of 20-50 or whatever.

16:50 dalet: anyone know who I mail to get this page updated? http://clojure.org/community

16:50 devn: I'd post something to the list. I think at one point it was Rich, but don't quote me on that.

16:51 dalet: ok cheers

16:51 devn: The list seems like a good way to go so if someone else can do the work...

16:51 technomancy: took me four or five times to get my update in

16:51 bartj: chouser, my train of thought could be wrong

16:52 devn: technomancy: who'd you bug? rich?

16:52 dnolen: devn: I think stuart halloway has access to.

16:52 devn: ah, that'd make sense

16:52 bartj: but, here goes:

16:53 technomancy: devn: I don't remember who ended up actually updating it, I just chimed in every time that page was mentioned on the list, and then one day I checked and it was there.

16:53 devn: btw, I'm defn, but I'm trying to unify my twitter handle and what not

16:53 err "consolidate" might be a better way to phrase it...

16:53 technomancy: ah :)

16:53 bartj: the songs have to be deduped, meaning that a couple of songs are duplicate

16:54 so I am currently capturing a fingerprint expanding that to multiple songs (and hence I would have multiple fingerprints)

16:54 and then remove these multiple fingerprints from the original 1M list

16:54 makes sense?

16:55 devn: bartj: im coming in late here, but is this a set or a map?

16:55 chouser: I don't know what you mean by expanding a fingerprint to multiple songs

16:57 bartj: devn, the fingerprints?

16:58 devn: bartj: what does the structure look like?

16:58 bartj: devn, it's a lazy seq

16:59 devn: bartj: so it's a list, a vector, a map, or a set

16:59 hehe

17:00 devinus: this lisp journey i'm on is exhausting.

17:01 devn: devinus: but rewarding!

17:01 bartj: list

17:01 Crowb4r: it's ok my hand cramps up as well from all the ()

17:01 devn: bartj: i dont know enough about your problem, im sorry

17:01 Crowb4r: :p

17:01 devn: oh god, stop with the parentheses jokes!

17:01 Crowb4r: :'(

17:02 devn: i heard a really funny quote by raganwald (a prominent figure in the ruby community (and proponent of functional programming techniques))

17:02 "They call them s-expressions, but if you're used to Lisp s-expressions, a Lisp s-expressions is like Ikea or Scandinavian furniture design, and Ruby's s-expressions are like what you find in the dumpster after Goodwill has picked through it and decided they don't even wanna sell that stuff."

17:03 Crowb4r: I switched to this keyboard layout just to make my life easier in lisp and pretty much anything no python. http://robey.lag.net/2008/09/20/coder-dvorak.html

17:03 devn: awesome

17:04 bartj: chouser, amalloy I don't think I can thank you enough for hearing me out /helping me for more than two hours

17:04 chouser: bartj: you're quite welcome, but your time's about up. Hope you figure it out!

17:05 devn: I really wish OOP languages would be more willing to try out FP techniques and solutions.

17:05 bartj: chouser, I think it is quite impossible to attempt explaining an algorithmic problem here

17:05 Crowb4r: C# is trying as long as it's over 3.0

17:05 devn: The melding of the two seems like such an important move for all of us.

17:05 Crowb4r: it supports lambda functions at least. :)

17:05 bartj: chouser, thanks again

17:06 tonyl: scala blends those 2

17:06 also javascript

17:06 and many more, i think

17:06 brehaut: and F#

17:06 devn: yes but as you dig deeper you realize how full of holes those implementations are

17:06 Crowb4r: Python 3.0 was like an FU to Lambda functions iirc.

17:07 devn: tonyl: i dont know much of scala so I can't speak to that. All I know is that it looks like writing Java, and I don't want to do that.

17:07 Crowb4r: PHP tried so hard to do first class functions and closures, but like all things PHP it just fell to it's doom.

17:07 devn: I want a sane object oriented language with hygenic macros and the whole ball of yarn.

17:08 Scala is... not what I had in mind...

17:08 brehaut: devn: clojure then?

17:08 Crowb4r: at least it uses a nice actor message passing

17:08 in scala

17:08 brehaut: devn: (only a half joking)

17:09 devn: brehaut: well actually no, you're right on target

17:09 clojure seems to be the only one that is combining the two

17:09 i wish more people were experimenting with that idea in established languages

17:09 Crowb4r: it's also taking flac for it, mainly because it's different.

17:10 devn: yeah i've been having this argument with people i work with -- they say this silly thing "embrace your constraints"

17:10 Crowb4r: I show off clojure or talk about it and it's just an uphill battle in most of my personal projects.

17:10 devn: which means: "we accept our problem as a solution"

17:11 it reminds me of the "bike shed" toxicity problem

17:11 everyone all of a sudden started calling everything a bike shed in order to squash debate

17:11 all it does is covertly promote academic inbreeding and intellectual laziness

17:11 Crowb4r: The STM is so nice for handling my transactions. I love it.

17:12 devn: yeah, but people dont know wtf it does until they learn how it works

17:12 when the only tool you have is a hammer (objects)

17:12 brehaut: devn: wadler's law to the rescue

17:12 devn: everything looks like a nail

17:12 Crowb4r: devn: yeah, I deal with that with a piticular C++ programmer and a PHP one.

17:12 * devn shrugs

17:12 devn: im confident we're all smarter than everyone else

17:12 ;)

17:12 Crowb4r: which are the worst due to having the shitties standards.

17:13 sorry my bad on the cursing

17:13 trying to explain the STM over locking is like talking to a wall.

17:13 devn: no shame in cursing. i placed a curse on Perl.

17:14 devinus: what's the current work going into clojure right now?

17:14 Crowb4r: Time to leave work, but be back to talk more in a little bit.

17:14 devinus: i'm guessing clojure-in-clojure ?

17:14 Crowb4r: closure in clojure

17:14 amalloy: devinus: performance

17:15 i think

17:15 * devn snickers

17:15 devn: pods!

17:16 Adamant: liberation from the JVM paradigm

17:16 devn: Java suffrage

17:16 so to speak

17:17 actually no, i think that is absolutely the wrong way to use suffrage after a brief google search

17:17 we want to *take away* Java's right to vote

17:17 Adamant: s/Java/Oracle

17:17 devn: ^^

17:18 * devn kills Oracle with fire

17:18 devinus: interesting

17:18 so is clojure going to start wrapping java methods?

17:18 Adamant: they are very good at making money. that's about all that can be said in their favor.

17:19 amalloy: guys, how is this discussion productive? clojure ML is having trouble with unfriendly attitudes, and now all that's being said in #clojure is slamming other languages and/or companies

17:19 devn: devinus: nono, the idea is to continue the current trend of making java irrelevant

17:19 brehaut: amalloy: right on

17:20 devn: amalloy: i sympathize, but there is some legitimate paranoia around oracle's control of the JVM

17:20 Adamant: amalloy: I talk smack about Oracle pretty much everywhere, but if it's not desired here I'll can it.

17:20 brehaut: also am i the only person who reads 'clojure ML' and immediately thinks of the family of static function languages?

17:20 Adamant: brehaut: no

17:20 devn: brehaut: definitely not :D

17:20 amalloy: brehaut: yeah, me too tbh. but i see it written so often...

17:20 devn: amalloy: it's trendy

17:21 trends are a funny thing in any lisp community

17:21 devinus: what's clojure ML?

17:21 tonyl: devinus: ditto

17:21 Adamant: mailing list

17:21 devinus: ah

17:21 * tonyl *facepalm*

17:21 devn: haha

17:21 Clojure in ML in ML on the ML

17:22 Adamant: I do think people should consider Oracle's existing rep in the MySQL community before getting too friendly with them, though

17:22 and how it got that way

17:23 devn: Guy Steele works for Oracle... They can't be all bad. Right guys? Right?

17:23 Adamant: the problem isn't with the ex-Sun guys.

17:24 technomancy: Steele won't last long

17:24 devinus: clojure in an ml language would actually be interesting

17:24 devn: Clojure in metalanguage in machine language on the mailing list, in markup language.

17:24 devinus: technomancy: lol, i was watching some interview with steele and a bunch of other language devs and he was talking smack about erlang

17:25 devn: devinus: from strange loop or?

17:25 Leonidas: why doesn't this work: (re-groups (re-matcher #"(a)b" "aba"))

17:25 devinus: devn: dont remember

17:25 devn: the panel with josh bloch and company?

17:25 devinus: yeah

17:25 Leonidas: I get an IllegalStateExtension

17:25 devn: heh -- they all were hating on Perl IIRC.

17:25 devinus: he basically misunderstands the whole let-it-fail philosophy with just "writing crap code"

17:26 amalloy: Leonidas: re-groups doesn't call .match

17:26 devn: but amalloy is right -- hate for other languages and companies and all of that. it's easy to descend from informed discussion into a lynch mob of smart people (who are notoriously good at being critical), bashing everything to hell

17:27 Adamant: nobody likes a c.l.l. grade discussion, true.

17:27 devn: one thing clojure has avoided is the whole "we're better than you" atmosphere that has surrounded other lisp communities

17:27 and it has been an incredible strength

17:27 so let's keep that going strong.

17:28 devinus: i'm currently learning CL and then plan to move to scheme and then get more into clojure after that

17:28 brehaut: devn: i think its hard to maintain that sort of attitude when a large chunk of the thought that has gone into clojure has come from other languages.

17:28 opqdonut: devinus: why on earth?

17:28 devinus: just so i can argue with facts :)

17:29 opqdonut: ^

17:29 devn: and, as should be noted, #clojure-casual does exist

17:29 tonyl: Leonidas: maybe this ##(re-find (re-matcher #"(a)b" "aba"))

17:29 sexpbot: ⟹ ["ab" "a"]

17:29 devn: opqdonut: knowing your history is a good thing.

17:29 ive dug into scheme lately

17:29 opqdonut: well, sure

17:29 devn: clojure is my "gets things done" language

17:30 Leonidas: tonyl: uhm, but that is not the group

17:30 opqdonut: I'm just thinking that learning three wholly different languages would give more bang for the buck

17:30 tonyl: it returns the string then the matched groups, in this case a

17:30 opqdonut: for instance clojure, lua, haskell

17:30 devn: opqdonut: in some sense i think you're right

17:30 Leonidas: amalloy: uhm, I'm pretty new to Clojure -- what does that mean.

17:31 devn: but there is an argument against that

17:31 amalloy: Leonidas: it's an artifact of the java matcher classes

17:31 devn: opqdonut: reading common lisp is a good way to understand how to write even better clojure code

17:31 because it's (in many ways), the same thing

17:32 Leonidas: amalloy: what do I need to do with it then?

17:32 call .match by myself?

17:32 amalloy: Leonidas: see tonyl's suggestion?

17:32 LauJensen: Just a quick heads up. ClojureQL is now in its final form for the 1.0 release, so what you see now on Github/Clojars is what will be release around 1/1/11 as 1.0 final. http://github.com/LauJensen/clojureql

17:32 brehaut: LauJensen: congrats

17:33 LauJensen: brehaut: thanks :)

17:33 AWizzArd: sounds good

17:33 Crowb4r: you guys see this? http://vintage-digital.com/hefner/misc/lisp-programmers.jpg

17:33 amalloy: Leonidas: and http://download.oracle.com/javase/1.5.0/docs/api/java/util/regex/Matcher.html#start%28%29 mentions that you need to call find() every time you want to look for a new match instead of ask about the old one

17:33 Crowb4r: SFW btw

17:34 tonyl: Thanks LauJensen for such a project, not only helps me in my sql endeavors but i look at the code more often to understand better clojure coding

17:34 LauJensen: tonyl: you're welcome, thanks for trying it out :)

17:34 Leonidas: amalloy: yeah, tonyl's suggestion does not work when I try to match multiple things

17:34 amalloy: Leonidas: ##(doc re-seq)

17:34 sexpbot: ⟹ "([re s]); Returns a lazy sequence of successive matches of pattern in string, using java.util.regex.Matcher.find(), each such match processed with re-groups."

17:35 Leonidas: amalloy: uhm, that looks interesting

17:36 amalloy: &(doall (re-seq #"(a|b)c" "rabc macl"))

17:36 sexpbot: ⟹ (["bc" "b"] ["ac" "a"])

17:37 raek: I have never used any of clojure's re functions other than 're-find', 're-seq' and 're-pattern'...

17:37 Crowb4r: what ever happpened to clojurebot?

17:37 raek: he's still here

17:37 ,1

17:38 clojurebot: 1

17:38 Crowb4r: ohh ok

17:39 Clinteger: what is the first character of sexpbot's output?

17:39 raek: a long implication arrow

17:39 Leonidas: amalloy: ok, re-seq seems to be exactly what I was looking for, thanks a lot!

17:39 Clinteger: hm, i cant see it in this font :(

17:39 amalloy: Clinteger: \u27F9

17:40 raek: http://www.fileformat.info/info/unicode/char/27f9/index.htm

17:40 Clinteger: thanks. doing $asc() gave me...something way different :p

17:43 celal: hi all, I have a question about lein

17:43 Clinteger: what fonts do you guys use? I only have one that can use it :|

17:43 show*

17:43 celal: when lein install is executed

17:44 I'm seeing a message that I should only see if the code is actually executed

17:44 devn: LauJensen: what about some sort of activerecord-esque abstraction on top of clojureql?

17:44 celal: shouldn't "lein install" only compile the code?

17:44 devn: LauJensen: (find_by_id 4), (find_by_name "hello"), etc.

17:44 technomancy: celal: you can't compile code in Clojure without executing it

17:44 LauJensen: devn: I believe what I have now is better

17:45 celal: hmm, so it is indeed going through my clj files, executing them to compile java classes from them, and then packaging the classes?

17:46 amalloy: celal: it has to. if you want something to not happen at compile time, then wrap it in a function which you only call at runtime, say from -main

17:46 celal: that's indeed what I am doing

17:46 I'm reading from a properties file in a function

17:46 raek: Clinteger: the DejaVu family has very wide unicode coverage and includes that one

17:47 Clinteger: it is also ugly ^^

17:47 celal: but somehow I see the error message from that function during "lein install"

17:47 mrBliss`: Clinteger: Inconsolata or Envy Code R

17:47 Clinteger: well i'm currently using calibri :<

17:48 i dont like to irc in fixed width

17:49 raek: I use Inconsolata for my terminal

17:49 celal: hmm, I think I have an idea now

17:49 raek: I don't know if it includes that char, or if it falls back to DejaVu

17:49 celal: I have a "def" somewhere, that calls that function

17:49 so I assume that function is executed because of the variable declaration

17:50 raek: yes

17:50 celal: I'll replace the variable declaration with something else

17:50 thanks guys

17:50 raek: when clojure code is AOT compiled, the files are evaluated

17:51 technomancy: celal: in most cases you can avoid AOT compilation if you don't need an executable jar

17:51 raek: I guess one could see compilation as evaluation that also stores the generated classes to files

17:52 celal: sorry, what does AOT stand for?

17:52 zakwilson: I just got a recruitment email on linkedin from dealer.com that mentioned they consider clojure experience a plus. I thought the channel would like to know.

17:52 raek: celal: Ahead-Of-Tme

17:52 *Time

17:52 celal: ahh, I see

17:53 hmm, is there a way to ask lein not to do AOT?

17:53 technomancy: celal: it only performs AOT if you ask it to, but including a :main namespace counts as asking.

17:53 celal: I think I wouldn't lose much by doing the compilation once on the fly during execution

17:53 got it

17:53 now it makes sense

17:53 I do have a main

18:17 ossareh: lo all

18:33 AWizzArd: ~seen rhickey

18:33 clojurebot: No entiendo

18:36 tonyl: $seen rhickey

18:36 sexpbot: rhickey was last seen quitting 2 weeks and 1 day ago.

18:39 celal: quit

18:46 ossareh: where would I find a good instructive piece on the scoping of functions attached to defrecords? I'm pretty hit and miss with function resolution with my records; (defprotocol A (m1 [this])) (defrecord B [] A (m1[this] (prn "B-m1"))). If these are in namespace "myns" I can access the m1 function on an instance of B - but in other namespaces where these are imported they're not always available (notable difference is in test cases.

18:54 raek: ossareh: the protocol methods are vars just like those introduced by defn. you require/use the methods of the protocol, rather than the record

18:55 the namespace of the defrecord must of course be loaded too, to make that record type's implementation of the protocol available

18:57 the record type must also be :imported (like a java class) if you want to access the constructor without the package prefix from another namespace

19:00 ossareh: but if you have those defninition you showed in the same namespace, I don't see why using/requiring the protocol methods should not work.

19:05 ossareh: thanks raek , with those examples I may have simplified it such that it does actually work. From what you've written I seem to get it

19:06 i.e. I'm using and importing according to what you have written - I think I might be missing something super simple - I'm now spellchecking my imports / etc :)

19:10 this was all working until I restructured the project, so I've brought in an issue at that point I guess.

19:12 raek: it can be a good idea to clear all namespaces (simplest way is perhaps to just restart the repl) every now and then to check that you haven't forgot a use or require somewhere

19:13 I tend to have to fix a lot of require/use problems when I restart my bot

19:13 after I have moved around functions

19:14 ossareh: raek: ye - I just fixed it, thanks for your help. I was being told it couldn't find an imported class, though I was unsure why, it seems there is some subtle relationship between using a namespace and the records in that namespace.

19:15 s/and the records/and importing the records/

19:15 sexpbot: <ossareh> raek: ye - I just fixed it, thanks for your help. I was being told it couldn't find an imported class, though I was unsure why, it seems there is some subtle relationship between using a namespace and importing the records in that namespace.

19:15 ossareh: sexpbot: you shouldn't do that unless asked :)

19:17 Raynes: Well, you did ask him!

19:17 He certainly didn't tell you to send a message to IRC starting with s/// ;)

19:18 Nonetheless, if you don't desire that functionality, you should be able to just prefix the message with a space. He should ignore that.

19:18 brehaut: curious that a piece of code now has a gender identity

19:19 Raynes: brehaut: He is androgynous. amalloy refers to him as a 'she', for example.

19:19 amalloy: i do not

19:19 technomancy: "he" is gender-neutral in English

19:20 brehaut: kids, learn from my fail

19:24 Raynes: technomancy: Seriously?

19:25 amalloy: Raynes: in a dictionary, yes. in a feminist newsletter, probably no

19:25 technomancy: Raynes: depends who you ask I guess. it's more like gender-undetermined.

19:25 Raynes: I learned something new today.

19:25 technomancy: maybe it's archaic

19:25 but I like archaic things

19:26 brehaut: technomancy: i think the caveat is that it has a gender specified when it used to reference a specific person?

19:26 amalloy: technomancy: it's still technically correct

19:26 brehaut: "If a person wants to do X, then he should do Y"

19:26 Raynes: brehaut: Or specific thing? Now, I sure do like sexpbot, but I still don't think of him as a person.

19:26 amalloy: is the correct gender-neutral phrasing, even though most people will tell you it should be "he or she"

19:26 clojurebot: max people is 317

19:27 Raynes: clojurebot: Cool story bro.

19:27 clojurebot: bartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.

19:28 brehaut: gentlemen pick your side: prescriptive or descriptive

19:28 personally, im on whatever side chomsky is on

19:30 amalloy: hah

19:30 ossareh: I tend to "she"

19:31 in the limit case it just wins you point :)

19:31 s/point/poins/

19:31 * ossareh gives up spelling.

19:36 pdk: xgoff i know you're gonna read this

19:37 so imma smile for the camera next time you google my name and #clojure

19:37 that is all

20:22 Leonidas: where should I ask if I want a small code review?

20:23 dnolen: Leonidas: here or on the mailing list.

20:24 Leonidas: dnolen: ok, thanks. Will ask tomorrow since its already 2 AM here :)

20:27 or, ok, I can read the mailinglist replies tomorrow as well…

20:30 scottj: Is there a function foo in clojure or contrib where (foo first inc [1 2 3]) => [2 2 3] and (foo butlast dec [1 2 3]) => [0 1 3] ? ideas for names for foo? right now I've got update-list and mapseq

20:32 technomancy: scottj: that doesn't really make sense since first returns a single element, while butlast returns a seq

20:32 it's not parallel

20:32 maybe if you replaced first with (partial take 1)

20:33 even then, you can't really take a function and map it to a subvec like that

20:33 scottj: well right now I've got it taking :first :butlast :rest and :last and there's separate code for each.

20:34 how come?

20:34 technomancy: (update-in x [0] inc) works because you can assoc onto x in position 0

20:35 scottj: http://paste.lisp.org/display/117948

20:35 technomancy: but calling (first x) returns a value that you can't correlate back to x

20:35 there's no setf-place, to use CL terminology

20:42 miltondsilva: Hi, does somebody knows why planetclojure isn't being updated?

20:53 ossareh: miltondsilva: I'm not sure - what are you hoping to get from it? clojure.org has a whole bunch or information, as does clojuredocs.org

20:54 miltondsilva: and the first google result for planet clojure turns up http://planet.clojure.in/ which seems pretty update to date.

20:54 technomancy: ossareh: no, it hasn't updated in over a week

20:55 ossareh: technomancy: I'm unfamiliar with how up to date it is usually.

20:55 miltondsilva: ossareh: planetclojure is a collection of blog posts... that's were I stay updated

20:56 ossareh: ah, I see - it harvests other sources into its list.

20:57 miltondsilva: yes... well.. I could do it my self... just add all blogs to a rss feed.. but then I would not know how to get new feeds :(

20:58 (new feeds = new blog)

20:58 blogs*

20:59 ossareh: miltondsilva: fair play, I'd not understood what it was initially - now I see what it is I see your issue. email alexott at gmail.com or b.ghose at freegeek.in ?

21:00 miltondsilva: not yet... but now I'm feeling inclined to do so

21:02 ossareh: sorry.. should use your name in the responses cause you might be expecting the alert from your client

21:02 brehaut: is there a way to get clojure.xml/emit to not emit trailing new lines after each element?

21:11 miltondsilva: brehaut: not sure.. but you could map the function trim-newline to the result

21:11 brehaut: miltondsilva: thats only going to remove the trailing newline from the whole document, rather than each element

21:12 looking at the code i think the answer is that im out of luck

21:16 miltondsilva: brehaut: it's a cheat trick.. but you could copy the original func.. and change println to print.. but you probably already figured that

21:16 brehaut: miltondsilva: yeah i had thought of that and im not super happy. maybe there is something magical in contrib

21:16 you'd think it wouldnt matter

21:16 but it appears pythons xml-rpc lib is a bit picky

21:41 miltondsilva: copy and paste wins :/

21:44 miltondsilva: brehaut: I also hate that feeling.. especially in clojure(because I always think I'm missing something)

21:44 brehaut: miltondsilva: that is exactly the feeling i have

21:45 miltondsilva: on the other hand, i think xml-rpc's rather (ahem) brief spec might be to blame here

21:47 miltondsilva: brehaut: can't use something else?

21:47 brehaut: miltondsilva: sadly no

21:50 amalloy: miltondsilva: i think Raynes wrote a clojure xml-rpc library

21:51 brehaut: amalloy: really? ive got one half done

21:51 Raynes: ping?

21:51 amalloy: brehaut: https://github.com/Raynes/clj-xmlrpc

21:52 brehaut: amalloy: im going to be kicking myself if this is older than mine

21:52 amalloy: brehaut: dec 6

21:52 Raynes: brehaut: ?

21:52 brehaut: amalloy: man talk about your syncronous development

21:52 Raynes: you are also writing an xml-rpc lib

21:53 Raynes: brehaut: Yessir.

21:53 brehaut: Raynes: lets join forces

21:53 https://github.com/brehaut/necessary-evil/

21:53 miltondsilva: brehaut: got to love the name

21:53 brehaut: miltondsilva: cheers :) it did have a sensible name, then i got some hate on for the spec

21:54 Raynes: is yours both client and server or just client?

21:54 Raynes: It's just a client.

21:55 Is yours a server implementation?

21:55 brehaut: Raynes: its both

21:55 although the server imp is incomplete

21:55 im building it ontop of ring

21:55 Raynes: The client isn't on top of ring is it?

21:55 brehaut: nope

21:56 clj-http

21:56 Raynes: If your client implementation is more complete/stable than mine (which is very likely), I'll just deprecate clj-xmlrpc.

21:56 Doubt anyone is using it anyway.

21:56 I'm not even using it yet.

21:57 brehaut: well, im not exactly using mine either. onyl just got the client talking to the python imp today

21:57 rata_: hi all

21:58 brehaut: hi rata

21:58 rata_: hi brehaut =)

21:58 Raynes: brehaut: If you see anything you'd like to steal in my implementation, steal away. I feel much better about your implementation than my own simply because I have very little interest in XML-RPC, and I probably never would have implemented a server-side unless I needed it badly.

21:59 brehaut: Raynes: i will do that

21:59 Raynes: brehaut: In any case, as long as your implementation is 'working', I feel safe deprecating my own in favor of it.

21:59 brehaut: Raynes: however: feel free to tell me ive done stupid things as im still a bit of a clj noob

21:59 Raynes: I'll take a look at the implementation tonight.

21:59 :>

21:59 brehaut: sweet as

22:00 Raynes: Not that mine was pretty...

22:00 brehaut: Could you show me an example of a request and the result of that request through necessary-evil? I'd like to compare it to clj-xmlrpc's output.

22:01 brehaut: Raynes: sure

22:03 Raynes: user=> (-> (MethodCall. :hello ["world"]) methodcall/unparse emit with-out-str)

22:04 "<?xml version='1.0' encoding='UTF-8'?>\n<methodCall><methodName>hello</methodName><params><param><value><string>world</string></value></param></params></methodCall>"

22:05 Raynes: I'm actually interested in the parse output.

22:05 brehaut: in terms of what the xml-rpc types get turned into?

22:06 Raynes: Right. xml-rpc would return a map with a :params key where each type had been parsed into the proper Clojure type.

22:06 brehaut: yeah

22:06 Raynes: Did you make dates parse into joda dates? I did that.

22:07 brehaut: <string> and nothing become a java string, <array> become vectors, <i4>s and <int> into Integers,

22:07 yup joda dates

22:07 structs into maps

22:07 Raynes: hi5

22:07 brehaut: hi5

22:07 Raynes: My implementation is very multimethodish.

22:08 brehaut: i use multis for the way in, and protocols for the way out

22:08 Raynes: I used multis for both.

22:08 brehaut: the guts of that stuff is inside value.clj

22:08 Raynes: I like your implementation.

22:08 It looks neat.

22:09 brehaut: hmm. i apparently missed out serialisation of base64

22:09 cheere

22:09 s/re/rs/

22:09 sexpbot: <brehaut> cheers

22:09 Raynes: Mine was rather throw-together and "Hey, I don't particularly care about xml-rpc, but I need to parse it, so...

22:09 "

22:09 brehaut: yeah its like that eh.

22:10 Raynes: brehaut: I handled base64 by decoding it and turning it into a byte array.

22:10 brehaut: i am apparently using org.apache.commons.codec.binary.Base64 to decode it?

22:10 Raynes: Well, the other way around.

22:11 (defmethod value-to-clj :base64 [{[i] :content}] (Base64/decodeBase64 (.getBytes i)))

22:11 Encoding it was (defmethod clj-to-value (Class/forName "[B") [x] [:base64 (String. (Base64/encodeBase64 x))])

22:12 brehaut: Raynes: can i use that Class/forName stuff in a protocol definition?

22:12 Raynes: I have no clue. That stuff scares me.

22:12 brehaut: likewise

22:13 Raynes: My library was a prerequisite to a blogging library that is still in the planning phase.

22:13 brehaut: Raynes: likewise

22:14 I started off wanting it for pingback

22:14 but i may also end up using it for metaweblog

22:14 Raynes: I have plans to write a blog editor in Clojure.

22:14 brehaut: Raynes: i got hold of marsedit for mac os x in a bundle so im just going to use that

22:14 Raynes: Everything sucks on Linux.

22:15 brehaut: aint that the truth ;)

22:15 im currently ssh port forwarding couchdb from my server to my local machine and using the futon DB admin to blog :P

22:15 Raynes: Well, as far as blog editors go.

22:15 :p

22:15 brehaut: heh

22:16 Raynes: Everybody swears by scribefire, but it "cleans up" html and mutilates any pasted code.

22:16 brehaut: yuck

22:17 Raynes: brehaut: I bet you could use that Class/forName stuff in extend-protocol.

22:17 Have you tried it yet?

22:17 brehaut: i havent

22:17 i hadnt thought to do it until you mentioned it above

22:18 Raynes: Actually, it probably doesn't. Looks like it *expects* a class name. defmethod just expects *something*.

22:19 Well, it accepts interfaces as well, but you see my point.

22:21 brehaut: hmm no

22:21 i get java.lang.RuntimeException: java.lang.UnsupportedOperationException: nth not supported on this type: Character (value.clj:90)

22:22 Raynes: Shame.

22:22 brehaut: yeah

22:22 squicky java edgecases :(

22:26 maybe i will have to brave the mailing list

22:35 Raynes: got it. just used 'extend'

22:35 (extend (Class/forName "[B")

22:35 ValueTypeElem

22:35 Raynes: brehaut: !

22:35 brehaut: {:value-type-elem (fn [this] (elem :base64 [(String. (Base64/encodeBase64 this))]))})

22:35 Raynes: Nice. :>

22:36 brehaut: it works but i cant help but wonder if there is a nicer way

22:41 Raynes: the prxml function you have used, does that take the standard xml structures that clojure.xml works with?

22:44 Raynes: apparently not

23:03 timmorgan: How can I know if a script is being run from the command line vs just used by another script?

23:06 lazy1: timmorgan: http://stackoverflow.com/questions/973106/what-is-the-clojure-equivalent-of-the-python-idiom-if-name-main

23:07 timmorgan: lazy1: thank you

23:16 lazy1: No worries, I don't think there is really a good option for that

23:26 technomancy: clojurebot: clj-http is <reply>I think you mean gnir.

23:26 clojurebot: 'Sea, mhuise.

23:27 brehaut: technomancy: i wanted to make that joke but didnt think anybody would get it

23:27 (inc technomancy)

23:27 sexpbot: ⟹ 4

23:28 technomancy: brehaut: I asked mcgrana at the Conj and he said he'd think about renaming it.

23:28 I don't think he thought particularly long about it though. =(

23:28 brehaut: awesome :D

23:28 not awesome :(

23:36 huh. of course ring has an input string for the body. why did that catch me off guard

23:42 woo! necessary-evil is two way

23:53 I am writing an ANN post for my XML-RPC lib; should i send it to the ring list of the general clojure list?

23:55 dougbradbury: how do I get from here {3 1, 2 2} back to here: (3 2 2). I need a reverse-frequencies function.

23:55 clojurebot: functions are maps

23:57 brehaut: dougbradbury: is order important?

23:57 dougbradbury: no

23:59 brehaut: no

23:59 brehaut: ok

23:59 amalloy: &(for [[k v] {3 1, 2 2, 0 3}] (repeat v k))

23:59 sexpbot: ⟹ ((3) (2 2) (0 0 0))

23:59 brehaut: amalloy: add a flatten around that

Logging service provided by n01se.net