#clojure logs

2010-12-21

02:19joshua__Not enjoying working with C++ at all.
02:19joshua__I'm helping my uncle by writing a bot for a program called CamFrog.
02:19joshua__After just having made a plugin for the sexpbot in this channel.
02:20joshua__Plugin in C++: 20+ files and hundreds of lines of code
02:20joshua__Plugin in Clojure: 1 file
02:21joshua__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.
02:22joshua__only need to store a string username and an int total_score (maybe a long but w/e)
02:23sandGorgonjoshua__, you could look into using sqlite or berkleydb (as embedded) or Postgresql (as full fledged RDBMS)
02:23Raynesjoshua__: You only need to store two values in total? Why use a database at all?
02:24amalloyjoshua__: yeah, what Raynes said
02:24joshua__Raynes: potentially hundreds of users actually, this program is likely to be very very popular.
02:24RaynesIf 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.
02:25amalloyjoshua__: even with thousands of users there's not much need for a database
02:25joshua__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.
02:25RaynesRight.
02:25RaynesJust a key-value store (a Clojure map) seems like it would be good enough.
02:26joshua__I don't think C++ lets you eval a source file actually ;p
02:26amalloyRaynes: 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
02:26Raynesamalloy: Well, he should write a Clojure reader of course.
02:26amalloyof course
02:26RaynesI was working under the pretense that he was going to implement Clojure in C++ as a prerequisite to the project.
02:26RaynesI am disappoint.
02:27RaynesNonetheless, it still stands. It could be stored as JSON just as well.
02:28joshua__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.
02:28amalloyjoshua__: right, i'm with Raynes again, though i'd use xml because json makes me twitch
02:28Raynesamalloy: I don't think I know you.
02:28amalloyjoshua__: not as big a pain as shipping a database engine with your bot :P
02:29joshua__amalloy: THAT is why I was so hesitant as to ask.
02:29joshua__joshua__, I was on the mongodb site going.. umm.. do I really want them to have to do this..
02:30amalloyjoshua__: 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
02:30amalloy(not endorsing this particular parser: just the first google hit)
02:31joshua__28 thumbs up in a stack overflow post so I guess I'll try it.
02:32joshua__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.
02:33joshua__Thank you for not naming "recieve a message" 0x02
02:33joshua__etc
02:33RaynesHah! :>
03:00joshua__amalloy, just realized there is an xml library already in the source tree so I'm abandonning the idea of using json
03:00joshua__midnight, give me a break =(
03:00amalloyRaynes: score one for amalloy
03:00joshua__at least I spotted it eventually
03:25zmyrgelI'm trying to find out how to profile my code
03:25zmyrgelI have a function test in one of my clj files which I want to test, it uses functions from other files
03:27zmyrgelin 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?
03:30zmyrgelone issue fixed with -cp project-0.1-standalone.jar but now I get understandable message, Main Method not found in game$test
03:32zmyrgelshould I just modify the code so I call my test function from projects main funtion is there a better way for it?
05:30kenshoHi. I'm looking into submitting the clojure contributor agreement. Is there a way to send the clojure contributor agreement via fax?
06:01AWizzArdkensho: I already asked a few times. Currently it is not an option to email/fax it.
06:01AWizzArdMusste mit der Post schicken ;)
06:02kenshoAWizzArd: I see thanks. Ich hoffe nur die Post verbockt es nicht :)
08:44AWizzArdIs instance? the right fn to find out if an object implements a specific Interface or Protocol?
08:45cemerickAWizzArd: instance? is right for interfaces, satisfies? is right for protocols
08:48AWizzArdAh good.
08:48AWizzArdThanks!
08:48AWizzArdcemerick: Would you in general prefer Protocols over definterface?
08:49AWizzArdIf you want to extend your Records with some fns.
08:49AWizzArd(or deftypes)
08:50cemerickI very rarely use definterface.
08:50susumuhi, I'm getting out of memory errors... I know where, but don't understand why. I've narrowed it down to these two examples:
08:50susumu(def not_out_of_mem
08:50susumu (let [result 0]
08:50susumu (reduce + result (range 50000000))))
08:50susumu(def out_of_mem
08:50susumu (reduce + 0 (range 50000000)))
08:51cemerickThat doesn't mean it doesn't have utility vs. protocols, just that my use cases tend to favor protocols.
08:51susumu(println out_of_mem2) blows the java heap every time.
08:52chousersusumu: surely you don't have to print it to cause it to blow the heap?
08:52susumusomething to do with (let result) allowing a local optimize?
08:52susumusorry, last line should have been: (println out_of_mem)
08:53susumuchouser: true, don't have to print it.
08:53AWizzArdcemerick: are definterfaces possibly more efficient? Do they allow type-hints that defprotocols don't?
08:54dnolenAWizzArd: because of that they are also more tedious. They don't create functions and you have type-hint to avoid reflection.
08:54chousersusumu: that's really interesting.
08:54susumufirst version, not_out_of_mem, doesn't cause out of memory errors.
08:54chouserI wonder if it's some kind of regression.
08:54chouser(reduce + 0 (range 50000000)) by itself also doesn't blow the heap
08:54dnolenAWizzArd: I found myself using them a lot more during the :static days, because protocols and :static did not play well together.
08:55susumuchouser: regression?
08:55chouserI mean, I wonder if this worked correctly in some (older) versions of Clojure.
08:56AWizzArddnolen: which is more tedious? a) definterface or b) defprotocol?
08:56dnolenAWizzArd: definterface
08:56AWizzArddnolen: what advantage does definterface over defprotocol?
08:56AWizzArdCan definterface type-hint more? Is it more efficient, because it can decide at compile-time what to do?
08:56susumusame behavior in clojure 1.1.0 (just tried it)
08:57cemerickAWizzArd: it's true, protocols don't support hinting of the corresponding methods.
08:58cemerickThat doesn't have much of anything to do with compile-time though.
08:58dnolenAWizzArd: 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.
08:59AWizzArdWhat 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.
09:00AWizzArdI 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
09:01AWizzArdAnd also have it making use of the typehint that my macro added to my-macroed-defn
09:01AWizzArdI will try it out :)
09:02cemerickAWizzArd: protocol fns can be hinted, they just don't pass through to the generated interface.
09:03chouserAWizzArd: It looks like you can type hint a protocol fn's return value
09:03dnolencemerick: so it's just for documentation purposes?
09:03cemerickdnolen: no, the hint is as effective as hinting a regular fn w.r.t. avoiding reflection on return values
09:03dnolenwhenever I tried type-hinting protocols it seemed to cause me trouble.
09:03chousersuch 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
09:04dnolencemerick: oh, sorry I see type-hinting the *return* value.
09:04cemerickright
09:04chousersusumu: I'm pretty well stumped
09:04cemerickIt'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.
09:05susumuchouser: me too... going to post on google groups
09:05AWizzArdHmm yes, it works so far.
09:05chousersusumu: My next thoughts are to examine the bytecode generated by 'def' and/or profile the running code. Both rather intimidating.
09:06AWizzArdI said (defprotocol my-proto (^java.awt.Component get-container [this]))
09:07dnolenchouser: interesting 1.3.0 doesn't exhibit that issue.
09:07dnolenalpha4 anyway
09:13chouserdnolen: really!? I'm seeing it.
09:14chouseroh, maybe not alpha4
09:16chouserI'm seeing it on Clojure 1.3.0-alpha4
09:16chouserstrangest to me is that (def x <reduce>) breaks but <reduce> works fine
09:16dnolenchouser: oh sorry, I was actually using SNAPSHOT
09:18dnolenactually I'm perhaps I'm not seeing it because my JVM settings are -Xms1024M -Xmx2048M
09:18chouserI'm running with -Xmx2m
09:19chouserohhhh
09:19cemerickyou mean 2g?
09:19chouserno
09:20chouserfor OOM tests like this, you don't have to wait as long for failure if you keep a small heap
09:20chouserI bet this is a protocol caching thing
09:20cemerickI wouldn't have even thought one could get a REPL with 2m.
09:21chouserbah. nevermind. spoke too soon
09:21chouser(def out_of_mem (last (range 50000000))) fails, no protocol in sight
09:22chouser(def ok (let [] (last (range 50000000)))) works fine
09:22dnolenchouser: yeah, when I run (def x (reduce + 0 (range 50000000)), my memory explodes to ~1.35gb of RAM
09:24dnolenisn't this just explicit head holding? (i.e. something that locals clearing can't handle?)
09:24mduerksenchouser, 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
09:25dnolenhmm, perhaps not, (def x (map inc (range 50000000))) is instantaneous
09:25chouserdnolen: lazy
09:25dnolenchouser: I know
09:25chouseroh
09:25dnolenI thought reduce was too.
09:25chouserno
09:25chouserreduce is eager
09:35AWizzArdThis is odd. I now added a non-hinted protocol fn and that too doesn't produce a reflection warning.
09:35AWizzArdIs there some kind of type-inference at work?
09:38dnolenyou 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.
09:38dnolenAWizzArd: big benefit of protocols, no type-hinting full speed ahead.
09:39AWizzArddnolen: yeah, though I combined this with a Swing method call.
09:39AWizzArd(.add my-frame (get-container2 (create-some-panel)))
09:40AWizzArdcreate-some-panel returns a (record) MyPanel instance. MyPanel implements a protocol fn get-container2 which is not type-hinted.
09:40AWizzArdSo (.add ^Object x) <-- should throw a reflection warning.
09:40AWizzArdforgot the my-frame
09:40AWizzArd(.add my-frame ^Object x) is what the compiler sees
09:41AWizzArdbecause get-container2 isn't type-hinted
09:41chouserAWizzArd: my-frame is a javax.swing.JFrame?
09:43bartjwhat does it mean when I see a: "call to sadd can't be resolved" reflection warning
09:43bartjand how would I go about fixing it?
09:43bartjwhere sadd is a function call from j-redis
09:44chouserbartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.
09:44clojurebotYou don't have to tell me twice.
09:44bartjit's syntax is as follows: (.sadd client param1 param2)
09:44jcromartieDoes anybody know if it's possible to do something like Seaside in Clojure, without continuations?
09:44AWizzArdchouser: yes
09:45bartjchouser, I am trying to improve performance by removing the reflection warnings
09:45AWizzArdchouser: I just tried another example and there I get a type-hint warning as expected.
09:45AWizzArdSo in general there is no type-inference mechanism. But for this one odd case I am not getting a warning.
09:46chouserAWizzArd: you're sure the protocol function doesn't know it's return type?
09:46chouserAWizzArd: (:tag (meta #'get-container2))
09:46AWizzArdchouser: 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.
09:47AWizzArdchouser: the call of :tag returns nil.
09:47AWizzArdfor get-container it returns java.awt.Component
09:47chouserbartj: 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.
09:48chouserAWizzArd: hmph
09:48AWizzArdpuzzeling
09:48chouserbartj: one way to do that is (.sadd ^ClientClass client param1 param2)
09:49chouserbartj: though you can hint client when you define it instead
09:49AWizzArdIt really seems to me that for some cases there is an implicit type-inference at work. Maybe something in the JVM, not in Clojure.
09:50AWizzArdBut 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.
09:51AWizzArdBut: can defprotocol do primitive type-hinting of function parameters?
09:51bartjchouser, thanks!, would I also need to type-hint "sadd"
09:52cemerickAWizzArd: no, but that's generally irrelevant
09:52AWizzArdOk, so that is the domain of definterface then.
09:52AWizzArdThis is might be the single one advantage of definterface over defprotocol.
09:52AWizzArdOr are there others?
09:52chouserbartj: the word ".sadd" itself? no. Only its arguments (client, param1, param2, etc.) would ever need to be hinted
09:53AWizzArdWell, 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 :)
09:54bartjchouser, why would you not want to type-hint "sadd" itself?
09:54AWizzArdchouser: why did you suggest to not type-hint unless one knows there is a performance hit?
09:55bartjchouser, "sadd" returns a type Java Map so, I was expecting to give (^Map .sadd ^Clientclass client...)
09:58chouserAWizzArd: why else would you clutter your code with them?
09:59AWizzArdchouser: yes, for performance reasons. Though it is in principle dependend on your editor, which could hide the type-hints.
09:59AWizzArdtechnomancy: 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:00AWizzArdchouser: In 1.3.3a the new thing was manually definde bindable vars. What changed in 1.3.4a?
10:00chouserbartj: 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:01bartjchouser, that is very informative, thanks
10:01chouserAWizzArd: normalized unchecked-* fn names; added *unchecked-math* support; fixes to binding conveyance (and *agent*)
10:01AWizzArdhmm
10:01AWizzArdDo you have an example what "normalizeq" means in this context?
10:02chouserAWizzArd: https://github.com/clojure/clojure/commit/3e644c768b1f769217ecd484c019580384c7a670
10:03AWizzArdthx
10:04AWizzArdoh interesting, the options map of defn accepts an :inline
10:05AWizzArdAnd I see that :static is still used. I thougt this was removed?
10:08chouser:inline is old. Useful, but an undocumented implementation detail that could go away at any time.
10:08chouserI believe :static is currently ignored, though as you note it is still attached to some core functions.
10:10AWizzArdYes, :static is still present in several functions.
10:10AWizzArdAnd :inline is also used here and there, also rhickey recently added some of them.
10:10AWizzArdFor example at https://github.com/clojure/clojure/commit/eb076dab7b7be68957922f47ad8d140e4ec579a1
10:10chouseryes. I enjoy exploiting :inline, but it's a dangerous game.
10:10AWizzArd;)
10:11chouserit allows you to create dual-nature vars, that act as macros or functions depending on how they're used
10:11AWizzArdYes. We both discussed this some weeks ago.
10:11chouserok
10:12AWizzArdI found this interesting.
10:12AWizzArdAnybody here who successfuly runs swank-clojure with Clojure 1.3.4alpha?
10:16bartjI see a bunch of reflection warnings in clojure/contrib/pprint/pretty_writer.clj
10:16bartjbut, I do not seem to have imported the clojure.contrib.pprint anywhere
10:32mduerksenchouser, susumu: any new insights regarding the heap-overflow issue?
10:35chousernope
10:56tonylhello
11:08AWizzArdHi tonyl.
11:32fhdHi. 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:34chouserfhd: 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:34fhdchouser: Ah, thanks
11:35AWizzArdBtw, 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:37leif-pHi, all. Is anyone present familiar with the labrepl exercises from Relevance?
11:38fhdleif-p: I've done a few.
11:42leif-pI 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:42fhdleif-p: Sorry, didn't get that far :(
11:45leif-pfhd: Ah, well, thanks anyway. Anyone want to field a basic concurrency question?
11:47tonylI would say just shoot the question and somebody would pick it up
11:48tonyl~anyone
11:48clojurebotPlease 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:59leif-pOK, 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:11AWizzArdI 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:11AWizzArd,(let [[_ n] (drop-while #(not (#{:key} %)) [1 2 3 4 5 :key 1000 6 7 8])] n)
12:11clojurebot1000
12:11AWizzArd(drop-while #(not (#{:key} %) coll) <-- better solution?
12:23leif-pAWizzArd: The second is just a step of your first solution, right?
12:27leif-pAWizzArd: Oops, sorry, you were asking "is there a better solution?" Nevermind.
12:28AWizzArdYes. The line I started with (drop-while ...) is what I currently have.
12:31tonylI 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:33tonylmaybe reduce, but that won't stop processing when it finds :key
12:34leif-pAWizzArd: 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:35tonylmaybe ##(drop-while (complement #{:key}) [1 2 3 4 5 :key 1000 6 7 8])
12:35sexpbot⟹ (:key 1000 6 7 8)
12:35tonylthen use second like leif-p says
12:36tonyl&(second (drop-while (complement #{:key}) [1 2 3 4 5 :key 1000 6 7 8]))
12:36sexpbot⟹ 1000
12:39amalloyleif-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:43amalloybut 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:48leif-pIt seems similar to table vs. row locking in databases, but I don't know if that analogy holds.
12:49amalloyleif-p: i think it's similar to row vs column locking :P
12:49amalloyyou have to wrap the whole thing in an atom/ref to get actual table locking
12:53leif-pamalloy: 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:54amalloyright
12:54amalloythough once you only have one ref it might as well be an atom
12:57AWizzArdtonyl and leif-p: thanks for your input.
12:58leif-pamalloy: So is my reasoning above correct, or am I misunderstanding refs?
12:58leif-pAWizzArd: np
12:58cemerickI suggest that the main Clojure mailing list be put back on full moderation for a spell.
12:58amalloyleif-p: what reasoning? the row-vs-column thing? or do you mean the really long message you tried to send that got clipped?
13:00amalloycemerick: i haven't been following. has the Ah-ha thread gotten bad too?
13:00cemerickamalloy: there's any number of bad threads. The s/n ratio has completely flipped around AFAICT.
13:00cemerickMaybe I have that impression because I only look when people send me mails/tweets/etc saying "whoa, what's up with the ML"?
13:01amalloycemerick: 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:02cemerickamalloy: only in a palliative capacity, unless I've missed something.
13:03amalloycemerick: wow, it's pretty rare that irc makes me look up a word
13:03amalloy$dict palliative
13:03sexpbotamalloy: adjective: Serving to palliate; serving to extenuate, mitigate, or alleviate.
13:04cemerickI think OS X's definition is more apt: "relieving pain or alleviating a problem without dealing with the underlying cause"
13:04amalloyah
13:04leif-pamalloy: I was not aware; my client never truncates/warns me. Here's my question: http://pastebin.com/T24s8x7H
13:05cemerickThere 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:06technomancycemerick: kinda feels to me like being in university when a bunch of freshmen flood in, all wowed by this one prof.
13:07cemericktechnomancy: I think that's putting it too lightly.
13:07amalloyleif-p: oh, i misread what the second approach was, the first time
13:07amalloythe second approach was indeed exactly what i suggested
13:10amalloythe 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:12AWizzArdtechnomancy: 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:13amalloya 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:15amalloyleif-p: ^^
13:18leif-pamalloy: 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:20amalloyleif-p: that's an interesting point. i guess i haven't had that sort of usage pattern before
13:22technomancyAWizzArd: I just got some patches from monsieur stuart s that allegedly improve support for 1.3; lemme push to clojars
13:23amalloyleif-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:25amalloyi 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:29AWizzArdtechnomancy: btw, is there a direct download link from clojars?
13:30technomancyAWizzArd: there is somewhere; couldn't tell you off the top of my head
13:31AWizzArdhttp://clojars.org/repo/swank-clojure/swank-clojure/1.3.0-SNAPSHOT/
13:32leif-pamalloy: 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:33amalloyleif-p: right, because imagine the alternative. you're iterating over a bunch of refs, right? so you have to deref them all
13:33AWizzArdtechnomancy: thx
13:34amalloythe 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:36amalloyrefs are not locks
13:41leif-pamalloy: 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:43amalloyleif-p: well, it's possible that what's wrong is me. i'm pretty sure this is why ensure exists, though
13:48amalloyleif-p: hm. interesting. i guess i'm wrong
13:48amalloywell, now i wonder what ensure is for
13:49amalloyleif-p: anyway, thanks for showing me this. hopefully we've both gotten a better understanding of refs
13:54leif-pamalloy: 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:57amalloyleif-p: https://gist.github.com/9313060b4a54377cdd67 is a quick test case i wrote that you can play with
13:59bartj, (remove #(contains? ["a" "b" "c"] %) ["a" "b" "c" "d" "e" "f"])
13:59clojurebot("a" "b" "c" "d" "e" "f")
13:59bartjI was expecting only "e" and "f" in the above experiment
13:59technomancyclojurebot: doc contains?
13:59clojurebotcontains? 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:02bartjtechnomancy, thank you
14:03bartjI have about five million items in a collection and I would like to remove 100 of them
14:03bartjcurrently I am using a clojure.set/difference
14:03bartjsomething like this: (clojure.set/difference (into #{} 5-million-items) (into #{} 100-items))
14:04bartjI was thinking about using a remove instead, since it is lazy
14:04leif-pbartj: (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:05amalloyleif-p: or indeed ##(remove #{"a" "b" "c"} ["a" "b" "c" "d" "e" "f"])
14:05sexpbot⟹ ("d" "e" "f")
14:05amalloybut all of those require putting everything into a set, which bartj seems to be avoiding
14:06amalloyotoh, bartj, you only have to put the 100 items into a set; the 5M can be processed lazily
14:07bartjto something like this: (remove #(.contains 100-items %) 5-million)
14:08leif-pamalloy: Ah, right you are. But (remove (set 100-items) huge-lazy-seq) can stream over the large data. Which you just said.
14:08leif-pI type too slowly. :)
14:08amalloyleif-p: #(foo %) is equivalent to just foo
14:09amalloybartj: (remove (set 100-items) 5-million)
14:09bartjamalloy, you mean taking advantage of the fact that the second collection in a clojure.set/difference can be lazy
14:09bartjhttps://groups.google.com/d/topic/clojure/7QVFwtXWAi8/discussion
14:11amalloybartj: no, that is kinda crazy
14:12amalloystu 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:19bartjamalloy, (a-set element) -> checks for the presence of the element in the set, right?
14:20bartjsimilarly, (a-vector element) -> returns vector[element]
14:20amalloybartj: indeed
14:21technomancybartj: if you're asking what the point of the contains? function is now, that means you're on the right track.
14:21bartjtechnomancy, you type fast!
14:22amalloybartj: it's the keyboard pants
14:22bartjamalloy, shirt pant?
14:24bartjIn any case, huge thanks to all
14:29cemerickThere are plenty of collection implementations that aren't also IFns…
14:30cemerickbartj, technomancy ^^
14:31fogus`http://fogus.me/fun/marginalia/ :-)
14:32bartjcemerick, like sequences ?
14:32technomancycemerick: I didn't say there wasn't a good answer =)
14:32bartj, ('(1 2 3) 1)
14:32clojurebotjava.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
14:34cemerickbartj: 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:44brehautfogus: perhaps you could use a minified version of syntax highligher if you are embeding it in every marginalia output?
14:45crowbar712000 lines?
14:45crowbar71:p
14:46brehautchouser: surely its language independant?
14:46chouserI think a line of Clojure probably weighs more than a line of Java
14:49Crowb4ryeah if it's C++ a ton of coe is just writing the memory managment on a small C++ program. :p
14:49Crowb4rs/coe/code/
14:49sexpbot<Crowb4r> yeah if it's C++ a ton of code is just writing the memory managment on a small C++ program. :p
14:50Crowb4rohh nice feature. ;)
14:50Crowb4rthought I was just being crafty.
14:51amalloy$sed -Crowb4r s/crafty/devious/
14:51sexpbot<Crowb4r> thought I was just being devious.
14:52Crowb4rohh that is super nice.
14:52amalloyCrowb4r: glad you like it!
14:53Crowb4ryou write him/her?
14:53amalloyRaynes mostly; the past couple months i've been working a lot on it too
14:54dnolenfogus`: marginalia is cool!
14:54Crowb4rahh, using the pirc framework for JAVA or roll your own?
14:54dnolenfogus`: I'm getting a lot of extra scrollbars in Safari tho.
14:54amalloyhe started from pirc and then rolled his own
14:54fogus`dnolen: Thanks. Yeah, it needs more work.
14:54amalloyand 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:55Crowb4rI may look into that. I use pirc myself. is the one you guys made faster then pirc?
14:55Crowb4ror just more idiomatic?
14:55fogus`brehaut: Thanks. That is a good idea.
14:57amalloyCrowb4r: no idea. i haven't looked at the internals
14:57Crowb4rahh ok
14:57Crowb4rI should toss Perrin on github and have you look at him.
14:57amalloybut it's at http://github.com/Raynes/irclj, i think, if you want to look
14:59Crowb4rI have a forecast feature and a last.fm feature as well.
14:59amalloy$seen LauJensen
14:59sexpbotLauJensen was last seen talking on #clojureql 1 minute and 42 seconds ago.
15:00dnolenfogus`: .syntaxhighlighter { ... overflow: visible !important; ... }, should fix it
15:00amalloyCrowb4r: damn. i was hoping to find someone who hadn't been hard from for a while
15:00dnolennot sure why there are so many !important styles. I hate !important
15:00fogus`dnolen: Thank you sir
15:00chouser$seen rhickey
15:00sexpbotrhickey was last seen quitting 2 weeks and 1 day ago.
15:00Crowb4ramalloy: huh? hard from for?
15:01amalloyheard
15:01arkhIs 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:02raekarkh: lein install?
15:03arkhraek: I'll read the docs on that - thank you
15:06cemerickThe miserable pile that is iterators and enumerations makes me wish black death upon those responsible.
15:06cemerick*serenity now*
15:07amalloycemerick: java.util.Enumeration, or java.lang.Enum?
15:07cemerickThe former, plus Collections/enumeration, and the whole lot that hangs with them.
15:07livingstonI 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:07amalloy&(doc spit)
15:07sexpbot⟹ "([f content & options]); Opposite of slurp. Opens f with writer, writes content, then closes f. Options passed to clojure.java.io/writer."
15:08amalloylivingston: (spit "file" (doall *foo*)) if the list isn't too long
15:08chouseror (split "file" (prn-str *foo*))
15:10livingstonamalloy: I treid that but the same thing happens but if I just type *foo* at the repl I see what I need
15:11livingstonchouser: that worked -- so what am I missing about the other way? I would assume it would have done what I expected?
15:11amalloylivingston: really? doall should force all the lazy seqs. maybe you should post a gist of what you're doing instead of a summary?
15:12Crowb4rSo what awesome things are going to be in 1.3?
15:12raeklivingston: spit writes strings to files. you have to make the form you want towrite into a string first
15:12raeklivingston: (spit "file" (pr-str *foo*))
15:12chouseramalloy: it does force it, the problem is .toString on a lazy seq always just prints the object id
15:12raekamalloy: even though the lazy seq is forced, it's still a lazy seq
15:12chouser,(str (lazy-seq '(1 2 3 4)))
15:12clojurebot"clojure.lang.LazySeq@e93c3"
15:13raekspit only calls str/.toString on the argument
15:13raek,(pr-str (lazy-seq '(1 2 3 4)))
15:13livingstonah I see - ok that makes more sense
15:13clojurebot"(1 2 3 4)"
15:13Crowb4rwouldn't apply str work as well?
15:13chouserif you want readable output, you want pr, prn, pr-str, or prn-str
15:13raekCrowb4r: for one level, I suppose so
15:13Crowb4r,(apply str (lazy-seq '(1 2 3 4)))
15:13clojurebot"1234"
15:14raekhrm, yeah...
15:14raeknevermind
15:14Crowb4rnot saying it's a good idea at all.
15:14livingstonok so in parallel, slurp brings in only a string too, right? what's the best way to turn that back to a list?
15:15raeklivingston: read-string
15:15raek(btw, why isn't that called "read-str"?)
15:17amalloyraek: i think it's because in pr-str pr is an abbreviation so we shorten str to match
15:17livingstonperfect... thanks (I miss lisp read etc.) that worked though
15:17amalloylivingston: read-string *is* lisp read
15:17tonylthere is still read for data structures, not strings
15:18livingstonexcept I have to bring the string in first, right? I can't call read read off the open file?
15:18livingstonoh nice there is just read ok.
15:18amalloy&(with-in-str "(foo blah a list)" (read))
15:18chouserread itself works on a stream, but read-string is easier to use when it's sufficient.
15:18sexpbot⟹ (foo blah a list)
15:19amalloylivingston: read-string just expands into the above
15:19livingstonit's a big string, I'd rather not bring it in twice.
15:19Crowb4rIs ther ea concise feature list for 1.3 anyplace?
15:20amalloylivingston: right. so (with-in-str (slurp file) (read) (read) (read)...)
15:20chouserCrowb4r: http://groups.google.com/group/clojure/msg/24c7696808bddfc7
15:22Crowb4rThank you
15:23livingstonwhy not (read (reader "file")) ? (alhtough I can't seem to find reader right now)
15:23chouserclojure.java.io/reade
15:23amalloylivingston: if you bound the reader and reused it, that would work too
15:24chouser(with-open [r (reader "file")] (read r))
15:24chouserbut note that read only reads one form. if you need more than that, you need to handle more complexity
15:24livingstonalhtough 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:24fogus`dnolen: Fixed. Thanks again.
15:25hiredmanif only there was a function that would repeatedly call other functions
15:25devinusok...when did clojure-contrib become such a pain to compile?
15:25livingston(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:25hiredmanwhen ss got his paws on the build
15:25Crowb4rSS?
15:25clojurebotI guess that is my answer.
15:25dnolenfogus`: nice
15:25tonyltrampoline, maybe?
15:25raeklivingston: with-open doesn't turn a BufferedReader into a PushbackReader. you'd have to do something like (PushbackReader. (reader ...))
15:27hiredmanstuart sierra
15:28devinusmodules/def/src/main/clojure/clojure/contrib/def.clj
15:28devinusis that truly necessary?
15:29chouserdevinus: I sympathize. On the other hand, in what way does that hurt you?
15:29devinuschouser: hurt? i wouldn't say hurt, other than i just had to click seven times to open up to the actual file
15:30technomancythat filename alone it takes up 1/3 of the width of my screen
15:30technomancywell, nearly a third
15:30devinusthere's like...nothing else in the files leading up to it
15:30brehautdevinus: conways law in action?
15:30technomancydevinus: java developers are typically paid by the directory.
15:30devinus:)
15:30devinustechnomancy: :P
15:30Crowb4rtechnomancy: LOL
15:31dnolendevinus: another victim of mavenization
15:31amalloytechnomancy: it takes up almost half of my screen; directories like that are no good for the visually-impaired
15:32technomancywe 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:32devinusamalloy: are you saying clojure hates blind people?
15:32technomancyincluding the people who suggested them in the first place
15:32devinus:O
15:33chousertechnomancy: maven-style paths but without maven?
15:33technomancychouser: we were on maven for quite some time
15:34devinusok, clojure question
15:34technomancy9 months or so
15:34devinusdoes clojure have a condition/restart system like CL?
15:34tonyltechnomancy: what style do you use now?
15:34technomancytonyl: src/foo/bar.clj
15:34chouserdevinus: there is error-kit in contrib. Do you have a need for actual restarts?
15:35chousertechnomancy: where do you put your java and antlr files?
15:35devinuschouser: maybe not yet, but i was curious
15:35chouserand your .css, .js, and .html?
15:35chouserdevinus: ah, good. that's roughly the spirit in which it was written
15:35technomancychouser: it's not a web app, but HTML and the like would go in resources/
15:36technomancychouser: 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:36chousertechnomancy: there will never be anything in src except clojure code?
15:37brehautargh. 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:37technomancychouser: there are some JS files for mapreduce jobs; they live in src/ like anything else
15:37technomancythat's why the filenames end in .js.
15:40cemerickJust out of curiosity, who's typing project-relative paths at all?
15:41bartjwhy would a call to a map function give a Stack Overflow?
15:41bartjsince map was lazy, I thought this was impossible
15:41chousersrc/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:41brehautbartj: the function map calls is still able to stack overflow
15:41chouserwhen forced
15:42cemerickchouser: I'd ask the same question re: com/company/project/foo.clj, too. *shrug*
15:42brehaut,(map (fn overflow [a] (overflow a)) [1])
15:42clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>
15:43chouser,(let [c (map (fn overflow [a] (overflow a)) [1])] 5)
15:43clojurebot5
15:43cemerickThat is, optimizing project layout for directory depth seems like a strange choice in general.
15:44chousercemerick: do you use your mouse while you're programming?
15:44cemericklike, is there a shortage of inodes on people's hard drives or something?
15:44brehautchouser: oh yeah true!
15:44Crowb4rI use lots of emacs and tab kay. :p
15:44chouserbrehaut: so depending on how precisely bartj's question was phrased...
15:45Crowb4rI'm use to the tab key tanks to python, so hitting tab for autocomplete is not a strech.
15:45cemerickchouser: Very rarely.
15:45Crowb4rs/tanks/thanks/
15:45sexpbot<Crowb4r> I'm use to the tab key thanks to python, so hitting tab for autocomplete is not a strech.
15:45chousercemerick: how do you open a file to edit?
15:46chousercemerick: I never click to do that, almost always type the path.
15:46rata_hi all
15:46Crowb4rhe does all his programming on a C64 still. :p
15:46bartjthe map is extremely simple
15:46cemerickchouser: Say the file I want is @ src/main/clojure/com/snowtide/pdf/io.clj -- Cmd-Shift-R, type "pdf/io", hit return.
15:46chouserit'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:47bartjand looks like this: (map #(String. (bytes %) "UTF-8"))))
15:47chousercemerick: cool!
15:47cemerickor, "c/s/p/io", if there's lots of ambiguity and I don't want to cursor through a bunch of options, etc.
15:47Lajlacemerick, I worship your shadow.
15:48Lajlabut only if you give me my new recur
15:48cemerickEclipse's matching in that regard is almost as good as TextMate's in that regard.
15:50bartjpity is all the errors in the stacktrace show clojure.lang or clojure.core
15:50bartjnothing in my files
15:50Crowb4rHmm, is there a good place to learn about java bytecode
15:50Crowb4rhttp://groups.google.com/group/clojure/msg/24c7696808bddfc7
15:50Crowb4ropps
15:50Crowb4rmy bad
15:50chouserbartj: don't give up. full stack traces are verbose, but almost always have the clues you need
15:51chouserbartj: 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:51rata_why (class ((update-in {} [1] conj 2) 1)) is clojure.lang.PersistentList?
15:51chouserthen paste it somewhere and we'll help
15:51amalloy&(class (conj nil 2))
15:51sexpbot⟹ clojure.lang.PersistentList
15:52chouserright. that is, conj on nil creates a list
15:53rata_mmm.. and why that?
15:54chouserwhat should it create?
15:55rata_mmm... I think PersistentList is ok =P
15:55chouser:-)
15:55rata_I have solved my bug anyway :)
15:56amalloyrata_: if you want it to create a vector you can
15:56amalloy&(class ((fnil conj []) nil 2))
15:56sexpbot⟹ clojure.lang.PersistentVector
15:56rata_oh thanks =)
15:57bartjhere is the stack trace - http://pastie.org/1396100
15:57chouserIt 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:57rata_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:57bartjThere are about five lines referencing clojure.core* and clojure.lang* which repeat ad-infinitum
15:57rata_so I don't have nils in my map
15:58amalloychouser: that would reverse the order of conj
15:58amalloy&(conj nil 1 2)
15:58sexpbot⟹ (2 1)
15:58amalloy&(conj [] 1 2)
15:58sexpbot⟹ [1 2]
15:59rata_sorry, (assoc-in ...)
15:59amalloyso it breaks backwards compatibility, possibly badly
15:59chouserit would indeed be a breaking change
16:00Crowb4rsounds like someting for a version 1.5 or 2.0 then. :p
16:00amalloyCrowb4r: no, 1.3 is all about horrible evil breaking changes, if you read the ML. maybe we could add some more
16:01chouserbartj: looks like you have a very deeply nested filters
16:01chouser& (nth (iterate #(filter identity %) [1]) 1000)
16:01chouser, (nth (iterate #(filter identity %) [1]) 1000)
16:01clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>
16:01chouser, (nth (iterate #(filter identity %) [1]) 10)
16:01clojurebot(1)
16:02Crowb4ramalloy: Oh awesome! Can I get in on these breaking changes!
16:02Crowb4rI like to break all sorts of things.
16:03bartj , (nth (iterate #(remove identity %) [1]) 1000)
16:04bartj, (nth (iterate #(remove identity %) [1]) 1000)
16:04clojurebot#<ExecutionException java.util.concurrent.ExecutionException: java.lang.StackOverflowError>
16:04bartjchouser, it's actually a remove instead of a filter
16:04chouseroh, interesting
16:04amalloychouser, bartj: i don't see how remove instead of filter matters
16:04chouser,(nth (iterate #(doall (remove identity %)) [1]) 1000)
16:04clojurebot()
16:05bartj(remove (set 100-items) couple-of-million-items)
16:05chouserbartj: that should be ok
16:05chousernote it's the remove-of-a-remove-of-a-remove-etc where all the steps are lazy that is the problem.
16:06chousera single lazy remove on a very large seq should be just fine
16:06chouseror making each step eager
16:06chouseras I did with doall above
16:06bartjchouser, it's the last step in a "loop", so my guess is that it would not be a nested-lazy
16:07bartjchouser, I could be wrong
16:07amalloybartj: yes it will
16:07chouserif you're recuring on the result of a remove, and doing a remove on that, they will nest
16:07amalloy(remove foo blah) returns a lazy seq representing a remove, which you then loop on, and layer another remove
16:07bartjah!
16:08chouserif you don't actually need the laziness, drop that doall in there and the problem should disappear
16:09amalloyor gradually build up a set to use as the remove-predicate, then do one remove at the end
16:10Crowb4rgeesh, I have been subscribed to the mailing list for about 10 months now and my clojure mail filter has nearly 12k in messages.
16:10bartjI thought Clojure tail recursion doesn't use a stack :(
16:10chouserbartj: it doesn't
16:10amalloybartj: it doesn't, but that's not relevant
16:11bartjthen, I am a bit non-plussed regarding the stack overflow
16:11chouserbartj: the stack overflows when you try to realize deeply nested lazy-seq-producers
16:12amalloybartj: *you* are using a stack, by layering N lazy filters on top of each other
16:12bartjhmm, ok
16:12amalloythen, when your loop/recur is finally done building this huge list of things to do, you realize the sequence all at once
16:12amalloywhich involves burrowing through the whole stack you made
16:12chouserin order to get the first item in (remove f s1), remove must force at least one step of s1
16:13chouserif s1 is itself (remove f s2), then s2 must be forced, etc.
16:13chouserso 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:15bartjamalloy, I thought we were being clever using (remove (set 100-set) million-items) in a loop
16:15bartjbut, I guess I was wrong, after all
16:16chouserthat 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:17bartjchouser, hmm, ok; would you say Clojure is ill-suited for this task of
16:17bartjremoving a small number of items from a very large set; until the large set is empty
16:18chouserno, 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:20chouserI couldn't recommend a different solution without understanding better what you're trying to do
16:20amalloychouser: right. so far the best solution for bartj's task is (let [million-items []]) - just empty the large list :)
16:21chouserheh
16:23chouserbartj: are you trying to discover the minimal set that includes all items from your million-items?
16:23bartjchouser, no
16:24bartjI have a million-items and after each iteration about 20-50 of them get deleted/removed
16:25amalloybartj: 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:25bartjI need to remove these 20-50 items from the million-items until there are no items in the million items
16:25chouserso 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:27bartjwell, yes
16:27amalloythen 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:28chouserok, 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:29bartjchouser, yes, but I still find that really slow
16:29Crowb4rSo who exactly are the mainline devs on clojure?
16:30chouserwell, that's new question then
16:30bartjI am trying to do a doall after say 20 iterations or x iterations
16:30chouserbartj: I doubt that'll be faster
16:30bartjbut, I am not sure if it would entirely help
16:32amalloychouser: does my proposal make sense? i'm not sure, myself
16:32chouseramalloy: seems vaguely plausible, given what we know of the problem.
16:33chouserbartj: where are these 20-50 item batches coming from?
16:34bartjok I'll come clean and explain the full problem
16:34bartjI have a list of a million songs and I am deduping them based on some fingerprint
16:35bartjwhere a fingerprint uniquely identifies the song
16:35bartjthere will be a couple of fingerprints/songs that are the exact copies of each other
16:35bartjand hence will be removed in the next iteration
16:36bartjso hence I have this:
16:38bartj(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:38bartjchouser, the 20-50 item batches are the duplicates in the above explaination
16:38chouserso you will eventually have to fingerprint every song
16:38bartjyes
16:40chouser,(let [songs (repeatedly 1000 #(rand-int 1e8)), fingerpseq (map #(rem % 10) songs), fingerpset (zipmap fingerpseq songs)] (vals fingerpset))
16:40clojurebot(82365500 36210571 29167172 10757843 66017534 81361065 90174516 12131347 14368608 22495869)
16:41devn:)
16:41chousers/fingerpset/fingerpmap/
16:41sexpbot<chouser> ,(let [songs (repeatedly 1000 #(rand-int 1e8)), fingerpseq (map #(rem % 10) songs), fingerpmap (zipmap fingerpseq songs)] (vals fingerpmap))
16:42chouserthat will lazily fingerprint each song, building a map of each fingerprint to exactly one song, returning a seq of one song per fingerprint
16:43bartjhmm, ok
16:43bartjthe main point is that I would be needing to efficiently remove the fingerprints in each iteration?
16:43chouserwhere songs are represented by random numbers, using their last digit as the fingerprint
16:43amalloychouser: the zipmap ruins all the laziness, doesn't it?
16:44amalloyi guess you have to do that anyway
16:44chouseramalloy: 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:45chouserbut the laziness means duplicate songs and fingerprints are not kept, for whatever that's worth.
16:45amalloyright
16:45chouserbartj: I don't yet see the value in doing "batches" of 20-50 or whatever.
16:50daletanyone know who I mail to get this page updated? http://clojure.org/community
16:50devnI'd post something to the list. I think at one point it was Rich, but don't quote me on that.
16:51daletok cheers
16:51devnThe list seems like a good way to go so if someone else can do the work...
16:51technomancytook me four or five times to get my update in
16:51bartjchouser, my train of thought could be wrong
16:52devntechnomancy: who'd you bug? rich?
16:52dnolendevn: I think stuart halloway has access to.
16:52devnah, that'd make sense
16:52bartjbut, here goes:
16:53technomancydevn: 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:53devnbtw, I'm defn, but I'm trying to unify my twitter handle and what not
16:53devnerr "consolidate" might be a better way to phrase it...
16:53devntechnomancy: ah :)
16:53bartjthe songs have to be deduped, meaning that a couple of songs are duplicate
16:54bartjso I am currently capturing a fingerprint expanding that to multiple songs (and hence I would have multiple fingerprints)
16:54bartjand then remove these multiple fingerprints from the original 1M list
16:54bartjmakes sense?
16:55devnbartj: im coming in late here, but is this a set or a map?
16:55chouserI don't know what you mean by expanding a fingerprint to multiple songs
16:57bartjdevn, the fingerprints?
16:58devnbartj: what does the structure look like?
16:58bartjdevn, it's a lazy seq
16:59devnbartj: so it's a list, a vector, a map, or a set
16:59devnhehe
17:00devinusthis lisp journey i'm on is exhausting.
17:01devndevinus: but rewarding!
17:01bartjlist
17:01Crowb4rit's ok my hand cramps up as well from all the ()
17:01devnbartj: i dont know enough about your problem, im sorry
17:01Crowb4r:p
17:01devnoh god, stop with the parentheses jokes!
17:01Crowb4r:'(
17:02devni heard a really funny quote by raganwald (a prominent figure in the ruby community (and proponent of functional programming techniques))
17:02devn"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:03Crowb4rI 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:03Crowb4rdevn: awesome
17:04bartjchouser, amalloy I don't think I can thank you enough for hearing me out /helping me for more than two hours
17:04chouserbartj: you're quite welcome, but your time's about up. Hope you figure it out!
17:05devnI really wish OOP languages would be more willing to try out FP techniques and solutions.
17:05bartjchouser, I think it is quite impossible to attempt explaining an algorithmic problem here
17:05Crowb4rC# is trying as long as it's over 3.0
17:05devnThe melding of the two seems like such an important move for all of us.
17:05Crowb4rit supports lambda functions at least. :)
17:05bartjchouser, thanks again
17:06tonylscala blends those 2
17:06tonylalso javascript
17:06tonyland many more, i think
17:06brehautand F#
17:06devnyes but as you dig deeper you realize how full of holes those implementations are
17:06Crowb4rPython 3.0 was like an FU to Lambda functions iirc.
17:07devntonyl: 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:07Crowb4rPHP tried so hard to do first class functions and closures, but like all things PHP it just fell to it's doom.
17:07devnI want a sane object oriented language with hygenic macros and the whole ball of yarn.
17:08devnScala is... not what I had in mind...
17:08brehautdevn: clojure then?
17:08Crowb4rat least it uses a nice actor message passing
17:08Crowb4rin scala
17:08brehautdevn: (only a half joking)
17:09devnbrehaut: well actually no, you're right on target
17:09devnclojure seems to be the only one that is combining the two
17:09devni wish more people were experimenting with that idea in established languages
17:09Crowb4rit's also taking flac for it, mainly because it's different.
17:10devnyeah i've been having this argument with people i work with -- they say this silly thing "embrace your constraints"
17:10Crowb4rI show off clojure or talk about it and it's just an uphill battle in most of my personal projects.
17:10devnwhich means: "we accept our problem as a solution"
17:11devnit reminds me of the "bike shed" toxicity problem
17:11devneveryone all of a sudden started calling everything a bike shed in order to squash debate
17:11devnall it does is covertly promote academic inbreeding and intellectual laziness
17:11Crowb4rThe STM is so nice for handling my transactions. I love it.
17:12devnyeah, but people dont know wtf it does until they learn how it works
17:12devnwhen the only tool you have is a hammer (objects)
17:12brehautdevn: wadler's law to the rescue
17:12devneverything looks like a nail
17:12Crowb4rdevn: yeah, I deal with that with a piticular C++ programmer and a PHP one.
17:12devnim confident we're all smarter than everyone else
17:12devn;)
17:12Crowb4rwhich are the worst due to having the shitties standards.
17:13Crowb4rsorry my bad on the cursing
17:13Crowb4rtrying to explain the STM over locking is like talking to a wall.
17:13devnno shame in cursing. i placed a curse on Perl.
17:14devinuswhat's the current work going into clojure right now?
17:14Crowb4rTime to leave work, but be back to talk more in a little bit.
17:14devinusi'm guessing clojure-in-clojure ?
17:14Crowb4rclosure in clojure
17:14amalloydevinus: performance
17:15amalloyi think
17:15devnpods!
17:16Adamantliberation from the JVM paradigm
17:16devnJava suffrage
17:16devnso to speak
17:17devnactually no, i think that is absolutely the wrong way to use suffrage after a brief google search
17:17devnwe want to *take away* Java's right to vote
17:17Adamants/Java/Oracle
17:17devn^^
17:18devinusinteresting
17:18devinusso is clojure going to start wrapping java methods?
17:18Adamantthey are very good at making money. that's about all that can be said in their favor.
17:19amalloyguys, 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:19devndevinus: nono, the idea is to continue the current trend of making java irrelevant
17:19brehautamalloy: right on
17:20devnamalloy: i sympathize, but there is some legitimate paranoia around oracle's control of the JVM
17:20Adamantamalloy: I talk smack about Oracle pretty much everywhere, but if it's not desired here I'll can it.
17:20brehautalso am i the only person who reads 'clojure ML' and immediately thinks of the family of static function languages?
17:20Adamantbrehaut: no
17:20devnbrehaut: definitely not :D
17:20amalloybrehaut: yeah, me too tbh. but i see it written so often...
17:20devnamalloy: it's trendy
17:21devntrends are a funny thing in any lisp community
17:21devinuswhat's clojure ML?
17:21tonyldevinus: ditto
17:21Adamantmailing list
17:21devinusah
17:21devnhaha
17:21devnClojure in ML in ML on the ML
17:22AdamantI do think people should consider Oracle's existing rep in the MySQL community before getting too friendly with them, though
17:22Adamantand how it got that way
17:23devnGuy Steele works for Oracle... They can't be all bad. Right guys? Right?
17:23Adamantthe problem isn't with the ex-Sun guys.
17:24technomancySteele won't last long
17:24devinusclojure in an ml language would actually be interesting
17:24devnClojure in metalanguage in machine language on the mailing list, in markup language.
17:24devinustechnomancy: lol, i was watching some interview with steele and a bunch of other language devs and he was talking smack about erlang
17:25devndevinus: from strange loop or?
17:25Leonidaswhy doesn't this work: (re-groups (re-matcher #"(a)b" "aba"))
17:25devinusdevn: dont remember
17:25devnthe panel with josh bloch and company?
17:25devinusyeah
17:25LeonidasI get an IllegalStateExtension
17:25devnheh -- they all were hating on Perl IIRC.
17:25devinushe basically misunderstands the whole let-it-fail philosophy with just "writing crap code"
17:26amalloyLeonidas: re-groups doesn't call .match
17:26devnbut 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:27Adamantnobody likes a c.l.l. grade discussion, true.
17:27devnone thing clojure has avoided is the whole "we're better than you" atmosphere that has surrounded other lisp communities
17:27devnand it has been an incredible strength
17:27devnso let's keep that going strong.
17:28devinusi'm currently learning CL and then plan to move to scheme and then get more into clojure after that
17:28brehautdevn: 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:28opqdonutdevinus: why on earth?
17:28devinusjust so i can argue with facts :)
17:29devinusopqdonut: ^
17:29devnand, as should be noted, #clojure-casual does exist
17:29tonylLeonidas: maybe this ##(re-find (re-matcher #"(a)b" "aba"))
17:29sexpbot⟹ ["ab" "a"]
17:29devnopqdonut: knowing your history is a good thing.
17:29devnive dug into scheme lately
17:29opqdonutwell, sure
17:29devnclojure is my "gets things done" language
17:30Leonidastonyl: uhm, but that is not the group
17:30opqdonutI'm just thinking that learning three wholly different languages would give more bang for the buck
17:30tonylit returns the string then the matched groups, in this case a
17:30opqdonutfor instance clojure, lua, haskell
17:30devnopqdonut: in some sense i think you're right
17:30Leonidasamalloy: uhm, I'm pretty new to Clojure -- what does that mean.
17:31devnbut there is an argument against that
17:31amalloyLeonidas: it's an artifact of the java matcher classes
17:31devnopqdonut: reading common lisp is a good way to understand how to write even better clojure code
17:31devnbecause it's (in many ways), the same thing
17:32Leonidasamalloy: what do I need to do with it then?
17:32Leonidascall .match by myself?
17:32amalloyLeonidas: see tonyl's suggestion?
17:32LauJensenJust 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:32brehautLauJensen: congrats
17:33LauJensenbrehaut: thanks :)
17:33AWizzArdsounds good
17:33Crowb4ryou guys see this? http://vintage-digital.com/hefner/misc/lisp-programmers.jpg
17:33amalloyLeonidas: 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:33Crowb4rSFW btw
17:34tonylThanks 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:34LauJensentonyl: you're welcome, thanks for trying it out :)
17:34Leonidasamalloy: yeah, tonyl's suggestion does not work when I try to match multiple things
17:34amalloyLeonidas: ##(doc re-seq)
17:34sexpbot⟹ "([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:35Leonidasamalloy: uhm, that looks interesting
17:36amalloy&(doall (re-seq #"(a|b)c" "rabc macl"))
17:36sexpbot⟹ (["bc" "b"] ["ac" "a"])
17:37raekI have never used any of clojure's re functions other than 're-find', 're-seq' and 're-pattern'...
17:37Crowb4rwhat ever happpened to clojurebot?
17:37raekhe's still here
17:37raek,1
17:38clojurebot1
17:38Crowb4rohh ok
17:39Clintegerwhat is the first character of sexpbot's output?
17:39raeka long implication arrow
17:39Leonidasamalloy: ok, re-seq seems to be exactly what I was looking for, thanks a lot!
17:39Clintegerhm, i cant see it in this font :(
17:39amalloyClinteger: \u27F9
17:40raekhttp://www.fileformat.info/info/unicode/char/27f9/index.htm
17:40Clintegerthanks. doing $asc() gave me...something way different :p
17:43celalhi all, I have a question about lein
17:43Clintegerwhat fonts do you guys use? I only have one that can use it :|
17:43Clintegershow*
17:43celalwhen lein install is executed
17:44celalI'm seeing a message that I should only see if the code is actually executed
17:44devnLauJensen: what about some sort of activerecord-esque abstraction on top of clojureql?
17:44celalshouldn't "lein install" only compile the code?
17:44devnLauJensen: (find_by_id 4), (find_by_name "hello"), etc.
17:44technomancycelal: you can't compile code in Clojure without executing it
17:44LauJensendevn: I believe what I have now is better
17:45celalhmm, so it is indeed going through my clj files, executing them to compile java classes from them, and then packaging the classes?
17:46amalloycelal: 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:46celalthat's indeed what I am doing
17:46celalI'm reading from a properties file in a function
17:46raekClinteger: the DejaVu family has very wide unicode coverage and includes that one
17:47Clintegerit is also ugly ^^
17:47celalbut somehow I see the error message from that function during "lein install"
17:47mrBliss`Clinteger: Inconsolata or Envy Code R
17:47Clintegerwell i'm currently using calibri :<
17:48Clintegeri dont like to irc in fixed width
17:49raekI use Inconsolata for my terminal
17:49celalhmm, I think I have an idea now
17:49raekI don't know if it includes that char, or if it falls back to DejaVu
17:49celalI have a "def" somewhere, that calls that function
17:49celalso I assume that function is executed because of the variable declaration
17:50raekyes
17:50celalI'll replace the variable declaration with something else
17:50celalthanks guys
17:50raekwhen clojure code is AOT compiled, the files are evaluated
17:51technomancycelal: in most cases you can avoid AOT compilation if you don't need an executable jar
17:51raekI guess one could see compilation as evaluation that also stores the generated classes to files
17:52celalsorry, what does AOT stand for?
17:52zakwilsonI 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:52raekcelal: Ahead-Of-Tme
17:52raek*Time
17:52celalahh, I see
17:53celalhmm, is there a way to ask lein not to do AOT?
17:53technomancycelal: it only performs AOT if you ask it to, but including a :main namespace counts as asking.
17:53celalI think I wouldn't lose much by doing the compilation once on the fly during execution
17:53celalgot it
17:53celalnow it makes sense
17:53celalI do have a main
18:17ossarehlo all
18:33AWizzArd~seen rhickey
18:33clojurebotNo entiendo
18:36tonyl$seen rhickey
18:36sexpbotrhickey was last seen quitting 2 weeks and 1 day ago.
18:39celalquit
18:46ossarehwhere 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:54raekossareh: the protocol methods are vars just like those introduced by defn. you require/use the methods of the protocol, rather than the record
18:55raekthe namespace of the defrecord must of course be loaded too, to make that record type's implementation of the protocol available
18:57raekthe 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:00raekossareh: 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:05ossarehthanks 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:06ossarehi.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:10ossarehthis was all working until I restructured the project, so I've brought in an issue at that point I guess.
19:12raekit 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:13raekI tend to have to fix a lot of require/use problems when I restart my bot
19:13raekafter I have moved around functions
19:14ossarehraek: 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:15ossarehs/and the records/and importing the records/
19:15sexpbot<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:15ossarehsexpbot: you shouldn't do that unless asked :)
19:17RaynesWell, you did ask him!
19:17RaynesHe certainly didn't tell you to send a message to IRC starting with s/// ;)
19:18RaynesNonetheless, if you don't desire that functionality, you should be able to just prefix the message with a space. He should ignore that.
19:18brehautcurious that a piece of code now has a gender identity
19:19Raynesbrehaut: He is androgynous. amalloy refers to him as a 'she', for example.
19:19amalloyi do not
19:19technomancy"he" is gender-neutral in English
19:20brehautkids, learn from my fail
19:24Raynestechnomancy: Seriously?
19:25amalloyRaynes: in a dictionary, yes. in a feminist newsletter, probably no
19:25technomancyRaynes: depends who you ask I guess. it's more like gender-undetermined.
19:25RaynesI learned something new today.
19:25technomancymaybe it's archaic
19:25technomancybut I like archaic things
19:26brehauttechnomancy: i think the caveat is that it has a gender specified when it used to reference a specific person?
19:26amalloytechnomancy: it's still technically correct
19:26amalloybrehaut: "If a person wants to do X, then he should do Y"
19:26Raynesbrehaut: Or specific thing? Now, I sure do like sexpbot, but I still don't think of him as a person.
19:26amalloyis the correct gender-neutral phrasing, even though most people will tell you it should be "he or she"
19:26clojurebotmax people is 317
19:27Raynesclojurebot: Cool story bro.
19:27clojurebotbartj: it's not broken. Unless you know the performance hit there is actually a problem, I'd recommend leaving it alone.
19:28brehautgentlemen pick your side: prescriptive or descriptive
19:28brehautpersonally, im on whatever side chomsky is on
19:30amalloyhah
19:30ossarehI tend to "she"
19:31ossarehin the limit case it just wins you point :)
19:31ossareh s/point/poins/
19:36pdkxgoff i know you're gonna read this
19:37pdkso imma smile for the camera next time you google my name and #clojure
19:37pdkthat is all
20:22Leonidaswhere should I ask if I want a small code review?
20:23dnolenLeonidas: here or on the mailing list.
20:24Leonidasdnolen: ok, thanks. Will ask tomorrow since its already 2 AM here :)
20:27Leonidasor, ok, I can read the mailinglist replies tomorrow as well…
20:30scottjIs 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:32technomancyscottj: that doesn't really make sense since first returns a single element, while butlast returns a seq
20:32technomancyit's not parallel
20:32technomancymaybe if you replaced first with (partial take 1)
20:33technomancyeven then, you can't really take a function and map it to a subvec like that
20:33scottjwell right now I've got it taking :first :butlast :rest and :last and there's separate code for each.
20:34scottjhow come?
20:34technomancy(update-in x [0] inc) works because you can assoc onto x in position 0
20:35scottjhttp://paste.lisp.org/display/117948
20:35technomancybut calling (first x) returns a value that you can't correlate back to x
20:35technomancythere's no setf-place, to use CL terminology
20:42miltondsilvaHi, does somebody knows why planetclojure isn't being updated?
20:53ossarehmiltondsilva: 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:54ossarehmiltondsilva: and the first google result for planet clojure turns up http://planet.clojure.in/ which seems pretty update to date.
20:54technomancyossareh: no, it hasn't updated in over a week
20:55ossarehtechnomancy: I'm unfamiliar with how up to date it is usually.
20:55miltondsilvaossareh: planetclojure is a collection of blog posts... that's were I stay updated
20:56ossarehah, I see - it harvests other sources into its list.
20:57miltondsilvayes... 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:58miltondsilva(new feeds = new blog)
20:58miltondsilvablogs*
20:59ossarehmiltondsilva: 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:00miltondsilvanot yet... but now I'm feeling inclined to do so
21:02miltondsilvaossareh: sorry.. should use your name in the responses cause you might be expecting the alert from your client
21:02brehautis there a way to get clojure.xml/emit to not emit trailing new lines after each element?
21:11miltondsilvabrehaut: not sure.. but you could map the function trim-newline to the result
21:11brehautmiltondsilva: thats only going to remove the trailing newline from the whole document, rather than each element
21:12brehautlooking at the code i think the answer is that im out of luck
21:16miltondsilvabrehaut: it's a cheat trick.. but you could copy the original func.. and change println to print.. but you probably already figured that
21:16brehautmiltondsilva: yeah i had thought of that and im not super happy. maybe there is something magical in contrib
21:16brehautyou'd think it wouldnt matter
21:16brehautbut it appears pythons xml-rpc lib is a bit picky
21:41brehautmiltondsilva: copy and paste wins :/
21:44miltondsilvabrehaut: I also hate that feeling.. especially in clojure(because I always think I'm missing something)
21:44brehautmiltondsilva: that is exactly the feeling i have
21:45brehautmiltondsilva: on the other hand, i think xml-rpc's rather (ahem) brief spec might be to blame here
21:47miltondsilvabrehaut: can't use something else?
21:47brehautmiltondsilva: sadly no
21:50amalloymiltondsilva: i think Raynes wrote a clojure xml-rpc library
21:51brehautamalloy: really? ive got one half done
21:51brehautRaynes: ping?
21:51amalloybrehaut: https://github.com/Raynes/clj-xmlrpc
21:52brehautamalloy: im going to be kicking myself if this is older than mine
21:52amalloybrehaut: dec 6
21:52Raynesbrehaut: ?
21:52brehautamalloy: man talk about your syncronous development
21:52brehautRaynes: you are also writing an xml-rpc lib
21:53Raynesbrehaut: Yessir.
21:53brehautRaynes: lets join forces
21:53brehauthttps://github.com/brehaut/necessary-evil/
21:53miltondsilvabrehaut: got to love the name
21:53brehautmiltondsilva: cheers :) it did have a sensible name, then i got some hate on for the spec
21:54brehautRaynes: is yours both client and server or just client?
21:54RaynesIt's just a client.
21:55RaynesIs yours a server implementation?
21:55brehautRaynes: its both
21:55brehautalthough the server imp is incomplete
21:55brehautim building it ontop of ring
21:55RaynesThe client isn't on top of ring is it?
21:55brehautnope
21:56brehautclj-http
21:56RaynesIf your client implementation is more complete/stable than mine (which is very likely), I'll just deprecate clj-xmlrpc.
21:56RaynesDoubt anyone is using it anyway.
21:56RaynesI'm not even using it yet.
21:57brehautwell, im not exactly using mine either. onyl just got the client talking to the python imp today
21:57rata_hi all
21:58brehauthi rata
21:58rata_hi brehaut =)
21:58Raynesbrehaut: 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:59brehautRaynes: i will do that
21:59Raynesbrehaut: In any case, as long as your implementation is 'working', I feel safe deprecating my own in favor of it.
21:59brehautRaynes: however: feel free to tell me ive done stupid things as im still a bit of a clj noob
21:59RaynesI'll take a look at the implementation tonight.
21:59Raynes:>
21:59brehautsweet as
22:00RaynesNot that mine was pretty...
22:00Raynesbrehaut: 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:01brehautRaynes: sure
22:03brehautRaynes: user=> (-> (MethodCall. :hello ["world"]) methodcall/unparse emit with-out-str)
22:04brehaut"<?xml version='1.0' encoding='UTF-8'?>\n<methodCall><methodName>hello</methodName><params><param><value><string>world</string></value></param></params></methodCall>"
22:05RaynesI'm actually interested in the parse output.
22:05brehautin terms of what the xml-rpc types get turned into?
22:06RaynesRight. xml-rpc would return a map with a :params key where each type had been parsed into the proper Clojure type.
22:06brehautyeah
22:06RaynesDid you make dates parse into joda dates? I did that.
22:07brehaut<string> and nothing become a java string, <array> become vectors, <i4>s and <int> into Integers,
22:07brehautyup joda dates
22:07brehautstructs into maps
22:07Rayneshi5
22:07brehauthi5
22:07RaynesMy implementation is very multimethodish.
22:08brehauti use multis for the way in, and protocols for the way out
22:08RaynesI used multis for both.
22:08brehautthe guts of that stuff is inside value.clj
22:08RaynesI like your implementation.
22:08RaynesIt looks neat.
22:09brehauthmm. i apparently missed out serialisation of base64
22:09brehautcheere
22:09brehauts/re/rs/
22:09sexpbot<brehaut> cheers
22:09RaynesMine was rather throw-together and "Hey, I don't particularly care about xml-rpc, but I need to parse it, so...
22:09Raynes"
22:09brehautyeah its like that eh.
22:10Raynesbrehaut: I handled base64 by decoding it and turning it into a byte array.
22:10brehauti am apparently using org.apache.commons.codec.binary.Base64 to decode it?
22:10RaynesWell, the other way around.
22:11Raynes(defmethod value-to-clj :base64 [{[i] :content}] (Base64/decodeBase64 (.getBytes i)))
22:11RaynesEncoding it was (defmethod clj-to-value (Class/forName "[B") [x] [:base64 (String. (Base64/encodeBase64 x))])
22:12brehautRaynes: can i use that Class/forName stuff in a protocol definition?
22:12RaynesI have no clue. That stuff scares me.
22:12brehautlikewise
22:13RaynesMy library was a prerequisite to a blogging library that is still in the planning phase.
22:13brehautRaynes: likewise
22:14brehautI started off wanting it for pingback
22:14brehautbut i may also end up using it for metaweblog
22:14RaynesI have plans to write a blog editor in Clojure.
22:14brehautRaynes: i got hold of marsedit for mac os x in a bundle so im just going to use that
22:14RaynesEverything sucks on Linux.
22:15brehautaint that the truth ;)
22:15brehautim currently ssh port forwarding couchdb from my server to my local machine and using the futon DB admin to blog :P
22:15RaynesWell, as far as blog editors go.
22:15Raynes:p
22:15brehautheh
22:16RaynesEverybody swears by scribefire, but it "cleans up" html and mutilates any pasted code.
22:16brehautyuck
22:17Raynesbrehaut: I bet you could use that Class/forName stuff in extend-protocol.
22:17RaynesHave you tried it yet?
22:17brehauti havent
22:17brehauti hadnt thought to do it until you mentioned it above
22:18RaynesActually, it probably doesn't. Looks like it *expects* a class name. defmethod just expects *something*.
22:19RaynesWell, it accepts interfaces as well, but you see my point.
22:21brehauthmm no
22:21brehauti get java.lang.RuntimeException: java.lang.UnsupportedOperationException: nth not supported on this type: Character (value.clj:90)
22:22RaynesShame.
22:22brehautyeah
22:22brehautsquicky java edgecases :(
22:26brehautmaybe i will have to brave the mailing list
22:35brehautRaynes: got it. just used 'extend'
22:35brehaut(extend (Class/forName "[B")
22:35brehaut ValueTypeElem
22:35Raynesbrehaut: !
22:35brehaut {:value-type-elem (fn [this] (elem :base64 [(String. (Base64/encodeBase64 this))]))})
22:35RaynesNice. :>
22:36brehautit works but i cant help but wonder if there is a nicer way
22:41brehautRaynes: the prxml function you have used, does that take the standard xml structures that clojure.xml works with?
22:44brehautRaynes: apparently not
23:03timmorganHow can I know if a script is being run from the command line vs just used by another script?
23:06lazy1timmorgan: http://stackoverflow.com/questions/973106/what-is-the-clojure-equivalent-of-the-python-idiom-if-name-main
23:07timmorganlazy1: thank you
23:16lazy1No worries, I don't think there is really a good option for that
23:26technomancyclojurebot: clj-http is <reply>I think you mean gnir.
23:26clojurebot'Sea, mhuise.
23:27brehauttechnomancy: i wanted to make that joke but didnt think anybody would get it
23:27brehaut(inc technomancy)
23:27sexpbot⟹ 4
23:28technomancybrehaut: I asked mcgrana at the Conj and he said he'd think about renaming it.
23:28technomancyI don't think he thought particularly long about it though. =(
23:28brehautawesome :D
23:28brehautnot awesome :(
23:36brehauthuh. of course ring has an input string for the body. why did that catch me off guard
23:42brehautwoo! necessary-evil is two way
23:53brehautI am writing an ANN post for my XML-RPC lib; should i send it to the ring list of the general clojure list?
23:55dougbradbury how do I get from here {3 1, 2 2} back to here: (3 2 2). I need a reverse-frequencies function.
23:55clojurebotfunctions are maps
23:57brehautdougbradbury: is order important?
23:57dougbradburyno
23:59dougbradburybrehaut: no
23:59brehautok
23:59amalloy&(for [[k v] {3 1, 2 2, 0 3}] (repeat v k))
23:59sexpbot⟹ ((3) (2 2) (0 0 0))
23:59brehautamalloy: add a flatten around that