#clojure log - Apr 12 2010

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

0:14 asimjalis: Suppose I wanted to represent Java as sexp, what would be a good notation for this? Are there any examples?

0:15 I want the notation to encompass all possible Java programs.

2:38 Licenser_: morning

3:12 asimjalis: Good morning Licenser.

3:13 What's a way to change *compile-path* before calling compile?

3:15 (binding)

3:15 "binding" ?

3:16 hiredman: ,(doc binding)

3:16 clojurebot: "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."

3:33 Licenser_: (doc compile)

3:33 clojurebot: "([lib]); Compiles the namespace named by the symbol lib into a set of classfiles. The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath."

3:33 Licenser_: hi Raynes

3:33 Raynes: Licenser: Hello.

3:34 Licenser_: I've played with the . replacement earlyer

3:35 dcnstrct: ,(org.apache.commons.codec.binary.Base64/encodeBase64String "foo")

3:35 clojurebot: java.lang.ClassNotFoundException: org.apache.commons.codec.binary.Base64

3:36 Raynes: Licenser: Any progress?

3:36 Licenser_: Raynes: yes and no :P it's not trivial

3:37 I managed to replace all dot's with something else but it now does not like the function names since it tries to resolve them :P and I am not entirely sure how to quote them

3:37 Raynes: Hehe.

3:40 Licenser_: sucks to be me :(

3:41 TheBusby: any hints on how to use contrib's slurp* with Shift-JIS encoded HTML?

3:42 Chousuke: hmmh.

3:42 ~def slurp*

3:42 clojurebot: Titim gan éirí ort.

3:42 Chousuke: meh

3:42 doesn't it take an encoding parameter?

3:43 TheBusby: ahh, slurp does but slurp* doesn't

3:43 looks like someone patched slurp https://code.google.com/p/clojure/issues/detail?id=121

3:46 dcnstrct: slurp and spit are awesome names btw.. I hope they don't get changed to something boring.

3:46 Chousuke: I wonder if GC already has an API to extract tickets from the issue tracker :/

3:46 the ticket to move them over to assembla is still open :P

3:47 bozhidar: while on the topic of files I was wondering what is the idiomatic way in clojure to work with binary records

3:47 Chousuke: dcnstrct: They also imply (correctly) that they're a bit crude :)

3:47 bozhidar: I can easily port my existing Java code, but it seems so ugly...

3:48 dcnstrct: b

3:48 err

3:49 ctrl-x b in the wrong terminal.. *sigh*

3:49 if only there was a way to get irssi to run in emacs...

3:50 hoeck: bozhidar: what is your java code using? nio?

3:50 bozhidar: hoeck: yes

3:51 I have a set of null separated binary records

3:51 hoeck: I guess its ok to use nio then

3:51 bozhidar: that I extract and decode, since they are actually text

3:52 hoeck: you could also use seqs of bytes, but I fear that this would be horribly inefficient

3:52 bozhidar: I was just wondering is there is some more clojurish may to do it

3:52 well efficiency is not that of a concern

3:53 hoeck: I'm currently trying to parse the mysql binary log in clojure, and I'm using nio

3:53 bozhidar: I'm teaching free programming courses at the technical university of sofia

3:53 and develop some small open source projects with my students

3:53 to give a feel of what real development is all about

3:54 and this is part of one of those projects

3:54 elegance is more important at this point for me, than efficiency

3:54 hoeck: thanks for the input, I guess I'll stick to nio

3:54 hoeck: when translating your code from java to clojure, you should try to write most functions in a immutable way, e.g. not using .put on your input-buffer, or incrementing counters

3:55 bozhidar: hoeck: I'm trying, but many years of C/C++/Java haven't done much good to my functional thinking

3:56 hoeck: : ), well, its never too late to start over

3:57 Chousuke: if you need to do parsing, you might want to take a look at fnparse for inspiration. maybe

3:57 hoeck: bozhidar: but even writing functional code in c helps understanding the code and makes it more elegant

3:57 Chousuke: I think I saw a DSL library for parsing binary data into data structures somewhere too

3:58 bozhidar: hoeck: when you're mostly working on business or "enterprise" projects the code you typically write all day is - set something/ get something

3:58 there is not a lot of room for creativity...

3:58 hoeck: bozhidar: and if elegance is that important, and you don't need nio specifc things like .position or .order, then building a lazy seq of bytes and parse that might be an elegant solution

3:59 I know :/

4:01 bozhidar: hoeck: I'm thinking the same thing about the lazy byte seq

4:02 that way I'd only need the decoder from nio

4:02 and code(although slow) will probably be much more clojurish

4:02 hiredman: , (read-string (binding [*print-dup* true] (pr-str (struct (create-struct :a :b) 1 2))))

4:02 clojurebot: java.lang.RuntimeException: java.lang.Exception: EvalReader not allowed when *read-eval* is false.

4:02 hiredman: ARGH

4:02 not even the exception I was looking for

4:06 ,(binding [*print-dup* true] (pr-str (struct (create-struct :a :b) 1 2)))

4:06 clojurebot: "#=(clojure.lang.PersistentStructMap/create {:a 1, :b 2})"

4:06 hiredman: and structmap has no such method as create

4:37 Licenser_: why can't I use binding to change the ns? I try to do: (binding [*ns* (create-ns 'bla)] (def a 1)) but it ain't working :(

4:37 ah found it

4:58 caljunior: anyone around who tried building couverjure recently?

5:00 ls

5:01 ls

5:02 oh crap

5:21 Raynes: kzar: ping

5:32 I feel so special. Who else here had grilled steak and sausage for breakfast?

6:54 licoresse: I am looking for an extended example of how to user the new defprotocl in 1.2

7:27 hamza: c.c.logging docs say, "Unless otherwise specified, the current namespace is used" but how can i tell it to use a different namespace so that i can get rid of #<core$ns_name__5578 clojure.core$ns_name... style junk from the logs.

7:35 sergey_miryanov: hi all!

7:36 i have a problem with mvn clojure:repl under windows. somebody can help me?

7:38 when i type symbols nothing prints on screen, after i press enter typed string prints on screen

7:38 it's really annoing

7:39 AWizzArd: Hi rhickey.

7:39 rhickey: hi

7:40 Great phrase from http://twitter.com/therealadam - "Clojure's novel simplicity vs. Scala's familiar complexity"

7:41 originally here: http://twitter.com/therealadam/statuses/12001324496

7:48 Licenser_: greetings rhickey

7:49 rhickey: hi

8:02 Licenser_: the more I can really code in clojure the nicer it looks

8:20 chouser: yeah, I saw that tweet. I think it overstates scala's familiarity (thinking of traits, auto-casting, type system details, etc.)

8:21 rhickey: well, is it the features that are familiar, the syntax, or the complexity?

8:30 chouser: the features and syntax are both superficially familiar I suppose

8:35 rhickey: I think the complexity is familiar too, if unrecognized. People just grok the usage rules of one feature at a time and fail to see the accretion of complexity

8:38 mfex: which of these is more clojure-ish? (apply conj '[a b] '[c d]) or (vec (concat '[a b] '[c d]))

8:39 chouser: that's a good point, and applies to features and syntax as well. no whole-hog new syntax, immutable locals, etc. as with clojure.

8:39 rhickey: mfex: neither: (into '[a b] '[c d])

8:40 chouser: and to be fair, scala led me if none too gently toward the immutable locals, lazy seqs (streams), and functional style.

8:40 mfex: rhickey: even better, thanks

8:41 rhickey: I love the quote, very succinct capturing of the issues

8:42 and once you overcome the novelty, you are left with simplicity, while in the other case you get the familiarity right away but are left with the complexity for good

8:43 chouser: yup

8:43 rhickey: obviously anything so pithy must oversimplify things a bit

8:44 chouser: I like the framing of it too -- as an observation of the ongoing choices of programmers

8:45 rhickey: chouser: yes, and I think no matter what is said, this true nature of the thing will determine the outcome

8:45 because you can't really talk someone into loving a programming language

8:46 chouser: very little of Clojure seems novel anymore. It's actually a bit boring.

8:46 perhaps this book is burning me out a little. heh.

8:46 rhickey: talk only gets people to try things

8:46 very little of Clojure is novel, depending on one's background

8:47 AWizzArd: Yes. A friend who did Mozart a long time understood basically all concepts extremly fast.

8:47 Thus, he found Clojure simple to use :)

8:49 chouser: rhickey: did you see my idea for a horrible hack on proxy ctors?

8:50 rhickey: chouser: no[e

8:50 nope

8:50 chouser: clojure-dev -- I'll get you a link.

8:51 because I just *know* you want to see my idea for a horrible hack. :-)

8:52 groups.google.com/group/clojure-dev/browse_thread/thread/8ffac5eac2e1f97a

8:53 http://groups.google.com/group/clojure-dev/browse_thread/thread/8ffac5eac2e1f97a

8:58 rhickey: chouser: but the problem still remains, if you needed access to any data, since that won't be there yet either

8:59 i.e. its fields are uninitialized, maybe a non-issue as each method impl is its own closure

9:00 but I'd hate to introduce behavior (apparent access to closed-overs) that we couldn't support in reify

9:01 and we can't, since its closed overs will be uninitialized fields

9:01 (should reify ever support bases with ctors)

9:01 sorry I didn't reply earlier - I had seen it but blocked it out in horror

9:01 :)

9:08 I'm ok with saying - sorry, the evil class made you use gen-class

9:32 chouser: rhickey: heh, yeah, ok.

10:07 slyphon: so if i want to write a java class that implements IMeta, er, how do i do that?

10:07 * slyphon googles!

10:13 dnolen: hmm, what is the idiomatic way to reset the value of an agent?

10:13 stuartsierra: dnolen: (send the-agent (constantly "foo"))

10:14 dnolen: stuartsierra: thx

10:19 chouser: slyphon: you want to write it in Java!?

10:20 esj: gents: are protocols meant to support variadics ? Mine are binding & as if it was a variable !

10:24 chouser: esj: no support for variadics in protocols (yet)

10:24 slyphon: chouser: i'm just writing a custom exception class

10:24 chouser: slyphon: have you looked at clojure.contrib.condition ?

10:24 slyphon: yeah, i'm running into trouble with the macro expansion

10:25 chouser: oh, ok.

10:25 esj: chouser: Thanks. Any idea on a timeframe for that ?

10:25 chouser: esj: haven't heard any mentioned, no.

10:26 slyphon: weird stuff, like java NPE in LispReader

10:26 and other stuff like trying to come up with a "general catch-all"

10:26 https://gist.github.com/9e189a0fb0b57683a778

10:26 esj: bummer. Its pretty central to a lot of stuff: (populate-type x & xs) etc etc

10:29 chouser: esj: rhickey is here, so perhaps he'll be inspired and have that fixed by lunchtime. :-)

10:30 rhickey: chouser: have what fixed?

10:30 chouser: rhickey: add support for variadics to protocols

10:31 "add" not "fix"

10:32 rhickey: ah

10:33 probably not, but you are only a wrapper function way from having an API that is variadic. Remeber, protocols are a minimal spec for implementations, not a totality of an API for users

10:34 away

10:34 (defn foo [x & xs] (do-foo x xs)) (defprotocol Foo (do-foo [x xs]))

10:37 dnolen: if you call shutdown-agents how do you start things back up again?

10:44 chouser: dnolen: don't call shutdown-agents until you're done. :-)

10:50 dnolen: hmm when driving an animation if you're going to use agent I suppose you have to use send-off and Thread sleep (and hard code a value based on the expected framerate), or is there a better way?

10:50 stuartsierra: dnolen: maybe a timer?

10:51 dnolen: stuartsierra: the timer that calls send-off on the agents ?

10:54 chouser: dnolen: There's an executor for calling functions at regular intervals

10:54 dnolen: chouser: in Clojure?

10:54 stuartsierra: dnolen: I was thinking a timer that observes the state of the agent at a fixed framerate and draws the animation

10:55 dnolen: stuartsierra: sadly the agent can't just keep ploughing through, the calculations take too long.

10:55 chouser: java.util.concurrent.Executors/newSingleThreadScheduledExecutor

10:55 is what I was thinking

10:55 dnolen: agent -> agents

10:56 stuartsierra: dnolen: What I mean is, do the calculations in the agent actions, and draw your animation in a separate thread.

10:57 dnolen: stuartsierra: that's what I'm doing.

10:57 but I need to throttle the agents because otherwise the actions pile up really fast

10:58 chouser: and I'm suggesting that instead of having an agent that calls itself with Thread/sleep, you might consider a ScheduledExecutor to call a fn at regular intervals for you

10:59 dnolen: chouser: hmm. what I'd really like to do is stick with agents but have some way to calculate the thread sleep based on how long the last action took to complete.

11:00 AWizzArd: Is it possible to have a FileInputStream or something like that which acts on a part of a file, for example marked by a byte offset and byte length?

11:01 stuartsierra: dnolen: If you (send *agent* action) within an agent action, it won't get sent until the current action completes. Is that what you want?

11:01 Licenser: ,(throw RuntimeException "Ruuuuuuun Forest Ruuuuuu!")

11:01 clojurebot: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.Throwable

11:01 Licenser: ,(throw (RuntimeException. "Ruuuuuuun Forest Ruuuuuu!"))

11:01 clojurebot: java.lang.RuntimeException: Ruuuuuuun Forest Ruuuuuu!

11:01 dnolen: stuartsierra: reall? I'm actually using send-off does that apply for send-off as well?

11:01 stuartsierra: dunon

11:01 dunno

11:02 S11001001: dnolen: it does, the only difference is that they use different thread pools

11:04 dnolen: hmm, (send *agent* action) causes poor animation, probably from coordination overhead?

11:05 S11001001: are you relying on the order of action execution?

11:05 stuartsierra: dnolen: still confused: are you drawing the animation in the action function?

11:05 dnolen: stuartsierra: no

11:05 stuartsierra: ok

11:07 dnolen: S11001001: I don't think so. The agents update the "boids" and the render loop reads out the snapshots and renders those.

11:07 stuartsierra: hmm, it doesn't look like (send *agent* action) waits

11:07 that's the problem.

11:07 even when I stopped my render loop, the agents kept burning on through their piled up actions

11:08 chouser: doesn't wait for what?

11:08 dnolen: chouser: stuartsierra above implied that the action doesn't get sent until the current action complete if you use (send *agent* action)

11:08 stuartsierra: no no

11:09 If you send an action WITHIN another action, it waits until the current action finishes.

11:09 chouser: if you do a 'send' or 'send-off' in an action, those don't get queued until the action you're in is done.

11:09 dnolen: stuartsierra: ahh I understand. Which explains the crazy pileup of actions and the reason I need Thread/sleep. I don't want the agent action queue to build up like that.

11:10 stuartsierra: So use the action itself to send the next action.

11:11 dnolen: stuartsierra: I'm getting confused now that's what I'm doing, http://gist.github.com/363662, you can just look at the bottom.

11:14 stuartsierra: I see. I'm not sure that send-off is the right thing to use there.

11:14 Plain "send" should work.

11:15 dnolen: stuartsierra: the animation suffers with send, actions pile up and it eventually slows to a crawl.

11:15 esj: chouser, rhickey: sorry for vanishing: work called. I'll look at that suggestion, thanks.

11:15 stuartsierra: dnolen: That shouldn't happen. There's something else going on.

11:15 triyo: "Joy of Clojure" has a quote in sec 4.1.2: "It is better to have 100 functions operate on one data abstraction than 10 functions on 10 data structures. -- Rich Hickey". I thought this was a Alan J. Perlis quote. ;-)

11:16 rhickey: triyo: It is a variant of Perlis, who said one data structure

11:17 dnolen: stuartsierra: not sure what that would be, the send part of this code is tiny. Without the send stuff this code works perfectly and the update/renderloop takes about 14-18ms

11:17 triyo: oh I see "one data abstraction"

11:18 esj: triyo: the chapter starts with the Perlis quote.

11:18 stuartsierra: dnolen: huh, I dunno, then

11:18 sorry

11:35 dnolen: setting up the agents on a separate thread with future and an infinite loop around send/await seems to be the simplest approach in my case, I can get rid of the thread sleep this way.

11:35 * dnolen is happy to hear better solution. knows rhickey isn't down with send/await

11:39 hiredman: dnolen: is there some reason you are using agents at all?

11:39 AWizzArd: Btw, what happened with the deftype issue? Are there now two deftypes? How are they called? deftype and defrecord?

11:39 dnolen: hiredman: seemed the easiest way to take advantage of multiple cpus

11:41 hiredman: are you using the stm at all?

11:41 dnolen: hiredman: not at all.

11:41 hiredman: I would look at using queues and executors directly

11:42 chouser: AWizzArd: nothing has changed yet. I think the current plan is 'defrecord'

11:43 AWizzArd: And defrecord will be what currently deftype is yes? But with implicit support for “:as this” and without having to explicitly declare clojure.lang.IPersistentMap?

11:43 dnolen: perhaps, but I was looking for a simple solution. what I can up with only required me to change a small portion of my program.

11:56 AWizzArd: Would it make sense to let all defrecords be java.io.Serializable?

11:56 cemerick: AWizzArd: I've prodded Rich on this before. I'm hoping.

11:57 Obviously not for long- or even medium-term storage, but to make stuff like session stores and such work reasonably.

12:03 AWizzArd: why not for long-term storage?

12:07 Licenser: AWizzArd: I guess becase serialisation might change over versions

12:07 cemerick: AWizzArd: because classnames will almost certainly change across versions.

12:08 AWizzArd: Ah ok

12:08 Licenser: I personally prefare a 'neutral' format for storage, json, yaml, (if it has to be) xml or somethin that isn't directly cuppled with the code

12:09 AWizzArd: Even then the class will have to be saved.

12:10 And that could be (deftype Foo [a b c]) (class (Foo 10 20 30)) ==> namespace.Foo__14052

12:10 but also with some other number

12:10 cemerick: this is what print-dup is intended to resolve

12:10 Licenser: AWizzArd: depends some kind of data structure

12:16 jfields: what's the best way to convert from a string to a double?

12:17 chouser: ,(Double/valueOf "5.1")

12:17 clojurebot: 5.1

12:17 dakrone: what's the difference between that and (Double/parseDouble "23")

12:17 jfields: I'm actually trying to (int) Double.parseDouble(element.getAttribute("Quantity").getValue()) - and I don't care about hard casting from double to int

12:17 dakrone: ?

12:17 jfields: cool, just wasn't sure if there was a nice clojure wrapper

12:17 chouser: ,(Integer/valueOf "5")

12:17 clojurebot: 5

12:18 jfields: ,(Integer/valueOf "5.1")

12:18 clojurebot: java.lang.NumberFormatException: For input string: "5.1"

12:18 chouser: ,(read-string "5.0")

12:18 clojurebot: 5.0

12:18 jfields: interesting, would you recommend read-string chouser?

12:18 chouser: ,(map read-string (.split #" " "5.0 5 5M 2/3 foo"))

12:18 clojurebot: (5.0 5 5M 2/3 foo)

12:19 chouser: ,(map #(class read-string %) (.split #" " "5.0 5 5M 2/3 foo"))

12:19 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$class

12:19 chouser: ,(map (comp class read-string) (.split #" " "5.0 5 5M 2/3 foo"))

12:19 clojurebot: (java.lang.Double java.lang.Integer java.math.BigDecimal clojure.lang.Ratio clojure.lang.Symbol)

12:19 jfields: ,(Integer/parseInt "5.1")

12:19 clojurebot: java.lang.NumberFormatException: For input string: "5.1"

12:20 chouser: jfields: depends on the context. If you always want an Integer and it's from an untrusted source, I'd use Integer/valueOf

12:20 jfields: chouser: cool, thanks.

12:21 chouser: if you want to allow a different radix, different types, etc. then read-string is an interesting option.

12:21 ,(read-string "2r010011000101")

12:21 clojurebot: 1221

12:22 jfields: it's coming from a trusted source that will always send doubles, so I don't think there's really much difference

12:23 what about converting from double to int in clojure, any recommendations?

12:23 ,(Math/round 5.1)

12:23 clojurebot: 5

12:23 chouser: right, just the Java stuff.

12:23 jfields: chouser: thanks.

12:23 chouser: well, I guess if you've got a Double you can use (int ...)

12:24 cemerick: ,(int 5.9)

12:24 clojurebot: 5

12:24 * cemerick just double-checks that those coercion fns don't round :-)

12:45 vegai: does that clojurebot work inside some kind of a sandbox?

12:45 chouser: yep

12:46 ,(System/exit 1)

12:46 clojurebot: java.security.AccessControlException: access denied (java.lang.RuntimePermission exitVM.1)

12:47 vegai: nice.

12:49 Raynes: $(System/exit 1)

12:49 sexpbot: 1

12:49 Raynes: Ugh.

12:49 I've screwed stuff up again.

12:50 vegai: huh?

12:50 $(+ 1 1)

12:50 sexpbot: 1

12:50 Raynes: I've screwed stuff up should suffice as an explanation.

12:50 vegai: ;)

12:50 ,(+ 1 1)

12:50 clojurebot: 2

12:50 vegai: ah, I'm still sane

12:50 relatively

12:54 it's hard to appreciate too much the fact that a language's name is unique

12:58 Raynes: $(+ 2 2)

12:58 sexpbot: 4

12:58 Raynes: $(System/exit 1)

12:58 sexpbot: Unable to resolve symbol: S in this context

12:58 Raynes: Well, it seemed fixed.

12:59 Oh, I see.

13:00 $(System/exit 1)

13:00 sexpbot: Unable to resolve symbol: S in this context

13:00 Raynes: Okay, time to go into debug mode. :|

13:03 By golly, I've fixed it.

13:03 $(System/exit 1)

13:03 sexpbot: DENIED!

13:03 vegai: $(+ 1 1)

13:03 sexpbot: 2

13:03 vegai: funny that breaking it caused that to evaluate to 1

13:03 Raynes: It was tricky, because the $( command requires a bit of special behavior.

13:03 vegai: or was everything evaling to 1?

13:04 Raynes: vegai: I'm not sure exactly how it was parsing the expression, but it was only evaling 1 because it was the last part.

13:04 $eval 1

13:04 sexpbot: 1

13:05 Raynes: $eval 1)

13:05 sexpbot: 1

13:05 Raynes: vegai: It was seeing it like this: System/exit 1), so it was only evaluating 1. :>

13:06 $eval System/exit 1)

13:06 sexpbot: Unable to find static field: exit in class java.lang.System

13:06 Raynes: Or not. It must not have seen the first part at all.

13:06 Odd.

13:07 drewr: Raynes: /j ##test

13:07 Raynes: drewr: I'm not testing the bot here.

13:07 I was demonstrating what I think was wrong because he asked. If that bothered anybody, they could have said so. :)

13:08 The bot is also in #clojure-casual for longer discussions or playtime.

13:12 Everytime I mention #clojure-casual here, at least 2 people do a quick spy mission to see how many people are there. :>

13:14 * shadowspar does a spy mission =)

13:14 dakrone: how many people are there? :P

13:15 Raynes: 7

13:15 Well, 6.

13:15 It's a young channel.

13:15 But it's a safe haven for when people like drewr and Lau Jensen ruin all your fun. :p

13:36 LauJensen: Hey team

13:36 dakrone: hey Lau

13:39 Raynes: LauJensen: Hai.

13:39 LauJensen: I was just talking about you.

13:39 <Raynes> But it's a safe haven for when people like drewr and Lau Jensen ruin all your fun. :p

13:40 LauJensen: What were you talking about? There's no safe haven from me and drewr ...

13:40 Raynes: #clojure-casual

13:41 LauJensen: ah

13:57 chouser: ,(map inc (range 5))

13:57 clojurebot: (1 2 3 4 5)

13:57 chouser: ,(binding [inc dec] (map inc (range 5)))

13:57 clojurebot: (-1 0 1 2 3)

13:57 chouser: ,(binding [inc dec] (pmap inc (range 5)))

13:57 clojurebot: (-1 0 1 2 3)

13:57 chouser: why!?

13:58 shouldn't that last one return (1 2 3 4 5) again?

13:58 hiredman: pmap is eager/lazy

13:58 cemerick: chouser: no

13:58 chouser: but it still does everything in other threads, doesn't it?

13:59 where inc should no longer have its thread-local binding to dec

14:00 oh... inc is dereferenced on the outside

14:00 pmap only sees the actual fn, not the var.

14:00 ok. I can feel my sanity returning.

14:00 cemerick: chouser: welcome back :-)

14:00 chouser: oh, you're here, are you? :-)

14:01 opqdonut: ,(binding [inc dec] (pmap (fn [x] (inc x)) (range 5)))

14:01 clojurebot: (1 2 3 4 5)

14:01 opqdonut: now the deref happens in each thread

14:01 cemerick: oftentimes.

14:01 chouser: right. thanks.

14:01 I just need to complicate my example a bit... :-/

14:02 cemerick: Someone tell all the clojure library writers to use the version config they have at their disposal, and stop using 1.0.0-SNAPSHOT.

14:02 * cemerick yells into the wind

14:03 * technomancy glances around nervously

14:03 technomancy: people don't actually use clojure-http-client, do they? =)

14:03 ipostelnik: technomancy, why?

14:04 The-Kenny: technomancy: I think I or one library I'm using use it somewhere

14:04 Raynes: technomancy: I use clj-apache-http.

14:04 :p

14:04 technomancy: just because I don't use it myself, but I wrote it =)

14:05 and it's stuck in 1.0.0-SNAPSHOT-land for that reason

14:05 ipostelnik: I think http.agent uses it

14:06 but I could be wrong

14:07 cemerick: technomancy: I certainly wasn't calling out anyone in particular. I just think hardly anyone writing clojure libs is particularly aware of the consequences of their versions, nevermind SNAPSHOT. There are libs that have had the same version since pre-1.1, and yet been breaking APIs like crazy and moving to some rev of 1.2's HEAD, and etc etc.

14:08 technomancy: yeah, it's only when you work on larger projects that spend 30s+ per build just checking for unnecessary snapshots that you feel the poin

14:09 *pain

14:09 cemerick: nah, it's when you're using a different version of clojure than the lib author or when the lib breaks long-standing fn signatures that you feel the pain :-)

14:10 technomancy: well breaking long-standing fn signatures w/o bumping major version numbers isn't SNAPSHOT-specific; it's just sloppiness IMHO.

14:10 but yeah, yuck

14:11 cemerick: well, one is ostensibly never supposed to republish any particular non-snapshot version, but yeah

14:11 and most repo managers prohibit it by default

14:12 technomancy: breaking in bugfix or point releases is what I'm thinking of

14:12 cemerick: sure

14:35 zakwilson: ,(rest "foo")

14:36 clojurebot: (\o \o)

14:36 zakwilson: ,(str (rest "foo"))

14:36 clojurebot: "(\\o \\o)"

14:36 zakwilson: Anybody know how to get what I want? (that being: "oo")

14:37 Nevermind. subs does it.

14:38 The-Kenny: zakwilson: Yeah, either .substr, something in c.c.str-utils2 or (apply str (rest "foo"))

14:38 .substr is propably the best method

14:39 carkh: ,(apply str (rest "foo"))

14:39 clojurebot: "oo"

14:39 chouser: (subs "foo" 1)

14:39 ,(subs "foo" 1)

14:40 clojurebot: "oo"

14:43 carkh: i like (rest "foo") it returns a nice little face =P

14:45 chouser: ,(symbol (str \\ \o) "")

14:45 clojurebot: \o/

14:45 carkh: haha awesome

14:45 The-Kenny: Oo, I didn't knew about subs

14:45 * The-Kenny always used .substring

14:48 The-Kenny: chouser: Hah, that's genius

14:49 technomancy: pet peeve: subs doesn't let you count from the end using negative offsets

15:01 chouser: ,(list (keyword "-"))

15:01 clojurebot: (:-)

15:19 stuartsierra: What do you do about "Invalid method Code length 68926"?

15:19 LauJensen: M-x apropos Invalid method Code

15:20 stuartsierra: I know what it means; I want to know if there's a way to ignore it.

15:22 It's a JVM limitation, so probably not.

15:23 chouser: split it up into multiple funcitons I suppose

15:24 stuartsierra: this is metacode

15:24 scottj: stuartsierra: do you have a bunch of data you can put in its own file and read in?

15:24 stuartsierra: it's a big macro expression

15:24 I can split it up, but less elegantly

15:24 chouser: write a macro that splits it up into multiple functions. :-)

15:24 stuartsierra: It's already a macro.

15:25 I think the problem is the macro is one giant expression: it fails at the compilation stage.

15:25 chouser: I'm just guessing, but if the problem is the amount of code inlined in a function, a closure should be able to pull out a chunk of it without losing your lexical context.

15:26 is it like (do a b c ... zzy zzz)?

15:26 stuartsierra: no

15:26 chouser: or more nested? or what?

15:26 stuartsierra: it's (describe *ns* ....every spec in this namespace...)

15:27 I don't have to write it that way, but it's convenient.

15:27 chouser: but what does that expand to?

15:28 stuartsierra: (alter-meta! *ns* assoc :spec #:TestContainer(:children [...every spec in this namespace...]))

15:28 The whole file is one big expression: that's where it's choking.

15:30 If I define all the specs (unit tests) within one expression, I can reload the namespace without any old specs left hanging around.

15:30 chouser: what if 'describe' expanded to (do (alter-meta! *ns* assoc :spec #:TestContainer{}) (alter-meta! *ns* update-in [:spec :children] conj spec1) (alter-meta! ... spec2) ...) ?

15:31 dunno if that would help or not, but that's the kind of thing I would try

15:31 stuartsierra: The compiler still has to generate one lambda to evaluate that, doesn't it?

15:32 chouser: possibly. but if it can be broken down like that, then you're back to (do a b c d ... zzz)

15:32 ...and then maybe you can do (do (#(a b c d)) (#(e f g h)) ... (#(zzz))) or something

15:34 * stuartsierra experiments

15:40 stuartsierra: does 'do' compile in a special way?

15:44 ok, wrapping macroexpansions in ((fn [] ...)) avoids the error

15:46 thanks

15:50 zkim: Is there a way to cons onto the end of a vector other than assoc?

15:51 kotarak: zkim: conj

15:51 ,(conj [1 2] 3)

15:51 clojurebot: [1 2 3]

15:51 zkim: kotarak: ah, thanks

16:24 chouser: ,(read-string (str (Exception. "foo")))

16:24 clojurebot: java.lang.RuntimeException: java.lang.Exception: Invalid token: java.lang.Exception:

16:25 chouser: that's just a weird-looking error.

16:25 zkim: lol

16:25 chouser: we'll pretend I wasn't actually seeing that in my unit tests...

16:26 zkim: Didn't see nothin

16:35 tomsw: I'd like to set a bunch of properties on a java object (an SWT Event) from a map. Is there an easy way?

16:36 (set! (. obj prop) value) assumes that prop is a symbol whose name denotes the field to modify

16:36 whereas in my case its value will be a symbol whose name etc.

16:37 chouser: these are fields you want to set, not setters you want to call?

16:37 tomsw: chouser: hello, yes

16:37 SWT Event has quite a few fields and no setter / getters

16:39 set! isn't what I expected it to be (a clojure macro) - maybe I'd be better off with reflection

16:39 chouser: bleh. you might do best to write your own macro

16:39 tomsw: yup

16:39 chouser: you want something like (set-many! obj prop1 val1, prop2 val2, ...) ?

16:41 tomsw: basically. I ended up with an Event factory with the various field names as keyword args, crap like (when keyCode (set! (. keyCode ev) keyCode))

16:41 chouser: oh, you said from a map

16:42 will it always be a literal map? (set-many! obj {:prop1 val1, :prop2 val2}) or do you want to support (set-many! obj a-map)

16:42 tomsw: well that was the other thing, keyword args in Clojure seem to be used (func {:arg1 v1 :arg2 v2}) instead of (func :arg1 v1 :arg2 v2)

16:43 chouser: nah, each is preferred by a different set of Clojurites.

16:43 I think rhickey is in the latter camp. :-)

16:43 tomsw: i better find out how to do the latter because I'm in that camp too, CL baggage I suppose

16:44 chouser: if you do it the latter way, it's clear you can't just pass in a map at runtime, which can allow you to do some clever performance things at compile time.

16:46 tomsw: well a (set-many! obj :prop1 v1 etc) macro would be a lot easier to write than a (set-many! obj map) one

16:51 I suppose the (set-many! obj prop-val-map) version would have to use eval?

17:01 StartsWithK: tomsw http://paste.pocoo.org/show/201170/

17:04 carkh: StartsWithK: did you have any success with fuzzy matching of java methods in clojure-mode ?

17:04 or swank-clojure really

17:05 StartsWithK: i never used emacs

17:05 wrong nick?

17:05 carkh: oh hum sorry .... must be someone else !

17:06 it was the-kenny =P

17:06 second word starts with k anyways

17:07 The-Kenny: carkh: Not really, sorry. I just played a bit around, nothing really serious.

17:07 carkh: no big deal, i was just curious

17:50 esj: excuse me clojure-bot...

17:50 ,(rem (nth ((fn fibo

17:50 ([]

17:50 clojurebot: EOF while reading

17:50 esj: (concat [0 1] (fibo 0 1)))

17:50 ([a b]

17:50 (let [n (+ a b)]

17:50 (lazy-seq

17:50 (cons n (fibo b n))))))) 1000000) 1000)

17:50 hmm.... that won't save you for long...

17:51 ,(rem (nth ((fn fibo ([] (concat [0 1] (fibo 0 1))) ([a b] (let [n (+ a b)] (lazy-seq (cons n (fibo b n))))))) 1000000) 1000)

17:51 clojurebot: Execution Timed Out

17:51 The-Kenny: esj: You can query clojurebot. That won't spam this channel

17:51 esj: actually it was all leading to a question

17:51 that code shouldn't cause a Heap overflow

17:52 according to http://groups.google.com/group/clojure/browse_thread/thread/57a12f1a0dab5e1b/cb3db6e6ac94092f?#cb3db6e6ac94092f

17:53 but it does on my machine. If I understand things, clojure should be GC'ing the seq as the calculation rolls along, but on my machine in getting a Heap overflow. What stupidity has trapped me this time ?

17:54 carkh: do you have any idea on the size of the bigint you're making ?

17:55 esj: carkh: what you're saying is that its a single number that's overflowing the heap ?!

17:56 carkh: hum looks like it isn't

17:56 it's working here

17:58 Chousuke: nth shouldn't hold the head either I guess

17:58 ,(nth (range 10000000) 10000)

17:58 clojurebot: 10000

17:58 carkh: thos my java process is now 1.6gb =P

17:58 Chousuke: hmm

17:58 ,(indexed? (range 10))

17:58 clojurebot: java.lang.Exception: Unable to resolve symbol: indexed? in this context

17:59 Chousuke: ,(instance? (range 10) clojure.lang.Indexed)

17:59 clojurebot: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Class

17:59 Chousuke: ,(instance? clojure.lang.Indexed (range 10))

17:59 clojurebot: false

17:59 Chousuke: meh

18:01 esj: carkh: I guess your GC figure it didn't need to run, so hasn't yet.

18:01 but what's exercising me, is that mine should have, but couldn't, apparently.

18:03 carkh: does it work with the fib-naive2 that's a bit lower int he thread ?

18:06 esj: carkh: that did work !

18:07 so the number can be represented, but something in the lazy-seq is going awry

18:08 carkh: ~def nth

18:09 lancepantz: can anyone make out what is wrong with this route? (defroutes actions (POST (route-compile "/:id/:action" {:id #"\w+-\d+" :action #"\d+"}) [id action] "hi"))

18:10 i get symbol cannot be cast as charSequence

18:10 it works just fine in a repl with the clout function only, only breaks when i put it in the defroutes

18:20 looks like that is a now fixed bug

19:16 programble: how do i tell if, for example, :foo is in a seqence?

19:16 [:foo :bar :baz] returns true

19:17 [ :bar :baz] returns false

19:17 arbscht: ,(.contains [:foo :bar :baz] :foo)

19:17 clojurebot: true

19:17 arbscht: ,(.contains [:bar :baz] :foo)

19:17 clojurebot: false

19:17 arbscht: that's one way

19:17 programble: ah

19:17 thanks

19:18 no more clojure-y way?

19:18 arbscht: that is clojure-y -- clojure is a hosted language ;)

19:19 technomancy: (contains? (set my-vec))

19:19 arbscht: ,(some #(= :foo %) [:foo :bar :baz])

19:19 clojurebot: true

19:19 arbscht: and so on

19:20 ,(clojure.contrib.seq/includes? [:foo :bar :baz] :foo)

19:20 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.seq

19:21 arbscht: ,(require 'clojure.contrib.seq)

19:21 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/seq__init.class or clojure/contrib/seq.clj on classpath:

19:21 arbscht: hrm

19:21 anyway, that's neater than some, if you don't mind the dependency

19:24 programble: urgh

19:24 clojure needs a re-split

19:25 technomancy: it's in contrib's str-utils, but yeah

19:25 and regexes need to be callable =\

19:25 programble: clojure.contrib.str-utils/re-split ?

19:26 arbscht: it's 'split' in the new string lib

19:30 programble: eh, ill just use (.split #"regex" s)

19:31 was writing a function to collapse whitespace

19:31 (defn collapse-whitespace [s] (->> s (.split #"\s+") seq (interpose " ") (apply str)))

19:32 it works

19:34 tomoj: do you think a better syntax could make this usable? https://gist.github.com/43e7d7d5248e6d639eea

19:35 I just don't like having to choose between -> and ->> :)

20:17 SynrG: hm. where do patches to the 'clj' script included in ClojureX go?

20:22 cheezey: so how would i go about making a lexer in clojure? :p

20:22 slyphon: hrm

20:24 cheezey: hrm =__= so like i would prefer it being recursive, or something ;x

20:24 i think most lexers are.. ?

20:24 carkh: you mean a lexer lexer or a parser ?

20:24 slyphon: gha

20:25 carkh: i mean, do you need a lexer specifically ?

20:25 * slyphon is confused as to how you do (fn [& args] (apply blah args)) inside a macro

20:26 cheezey: carkh: lexer im fairly certain. tokens and stuff right? :P

20:26 carkh: what's the goal ?

20:26 cheezey: carkh: lexing some maths. like 2+3+5

20:26 slyphon: maths!

20:26 carkh: i'd go for a full blown parser =P

20:26 using fnparse

20:27 http://github.com/joshua-choi/fnparse

20:27 cheezey: hm.. well so there's no easy way of doing this without the library?

20:28 carkh: a lexer will only go to a point

20:28 cheezey: well i mean i think i need a lexer eventually so that's why i'd like to learn it :o

20:28 carkh: there is a hierarchy in a math expression, a lexer won't proide you with that

20:28 provide*

20:28 cheezey: carkh: yeah i know. the parser will do that portion =XXX

20:28 so future question: how do i write a parser LoL

20:29 carkh: that second question, there are book written about it

20:29 booksss

20:29 slyphon: the dragon!

20:29 beware the dragon!

20:29 cheezey: carkh: i mean in clojure =_=

20:29 slyphon: the underlying principles are the same

20:29 cheezey: sorry im still new to functional so :\

20:29 carkh: well, even if you want to do it yourself, i'd skip the lexer part and go directly for a recursive descent parser

20:29 that's the easier to do

20:30 cheezey: i just dont know if im missing some command that would simplify it

20:31 carkh: but it's a lot of work with lots of edge cases, way easier to use an existing library

20:33 zakwilson: Should (clojure.contrib.duck-streams/spit "foo" a-map) produce output readable with (read-string (slurp "foo"))? I'm having a problem where the read throws "java.lang.Exception: Invalid token: :"

20:34 carkh: try replacing a-map with (with-out-str (prn a-map))

20:35 or pr instead of prn

20:37 ,(read-string (with-out-str (pr {:a "blah"})))

20:37 clojurebot: {:a "blah"}

20:38 zakwilson: Looks usable. Let's see if it breaks when fed a 26,000 item map.

20:38 carkh: ahwell then you should directly print to a stream

20:38 instead of passing through a string representation

20:39 zakwilson: I bought a machine with 4 gigs of RAM so I could properly abuse it!

20:39 cheezey: LoL

20:41 zakwilson: I'm just glad Clojure's maps are more space-efficient than Haskell's.

20:42 carkh: oh they are ?

20:44 zakwilson: A map of keywords to ints seems to use less than half the space of a Data.IntMap of 32-bit hashes to ints.

20:44 And a Data.Map String Int is even bigger.

20:44 Map operations in Haskell are faster though.

20:46 cheezey: this is probably a really dumb question but why can't i do (cond (true)(true))? o_O

20:46 zakwilson: Because true isn't a function.

20:47 ,(cond true true)

20:47 clojurebot: true

20:47 cheezey: ya i am dumb lulzzz

20:57 TheBusby: my favorite error message;

20:57 ,(let [count 5 mylist [1 2 3]] (count mylist))

20:57 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

20:58 hiredman: with invokedynamic you could inject the IFn interface into Number to name Numbers work like (0 [1]) => 1

20:59 Raynes: Would anybody find title-scraping of links useful? programble and I just added title scraping to sexpbot, but I didn't want to enable it here unless anybody thinks it might be useful.

20:59 It only scrapes the titles of a maximum of 3 links in a message.

21:01 Well, I have to go. I'll check back on that.

21:03 As a quick example, I'll leave this here http://github.com

21:03 sexpbot: Secure source code hosting and collaborative development - GitHub

21:03 zakwilson: (with-open [wtr (BufferedWriter. (FileWriter. "foo"))] (.write wtr (with-out-str (pr a-map)))) results in an empty file. That's... not what I expected. Should I just get some sleep?

21:04 Oh, wait... no it doesn't. I was looking at the wrong file. That settles it. I SHOULD just get some sleep.

21:04 scottj: Raynes: I think that's very useful.

21:05 _ato: probably want to turn it off for gists and pastebins and such though, that'd just get annoying fast

21:05 scottj: Raynes: I'd most like it on google groups and youtube links

21:13 Raynes: _ato: That would take a little redesigning, but turning it off for specific links is definitely doable. Good idea.

21:38 slyphon: argh

21:38 variadic macros are eating my brane

22:01 webwanderer: how do i get the index of a sequence i'm mapping through?

22:02 tomoj: clojure.contrib.seq-utils/indexed I think

22:03 webwanderer: cool

22:03 tomoj: ,(for [[i x] (map vector [:foo :bar :baz] (iterate inc 0))] [i x])

22:03 clojurebot: ([:foo 0] [:bar 1] [:baz 2])

22:28 TheBusby: anyone have any experience using java's CookieManager to access website content that requires login?

22:46 lancepantz: is there a neater way to write this?: (-> blob (get 1) (get 2) (get "edges") (get 0) (get "to_id"))

22:50 tomoj: ,(get-in [:foo [:bar :baz {"edges" [{"to_id" 10}]}]] [1 2 "edges" 0 "to_id"])

22:50 clojurebot: 10

22:50 tomoj: I'd be interested to hear how you're modeling graphs, if that's what you're doing

22:50 lancepantz: oh, perfect man

22:50 tomoj: clojure style is to use keywords instead of strings

22:50 :edges instead of "edges" I mean

22:51 hiredman: to-id vs to_id

22:51 lancepantz: yeah, i do in most places, this is just a test thats loading a blob from sql

22:51 tomoj: ah

22:51 lancepantz: and this is my graph library: http://github.com/ninjudd/jiraph

22:51 sexpbot: ninjudd's jiraph at master - GitHub

22:55 tomoj: lancepantz: very interesting

22:55 thanks

23:07 technomancy: oh man... I saw a thread titled "removing parentheses" on the mailing list... I was sure it was going to be about "let's make clojure use indentation instead of parens so the newbies will love it like Python!"

23:07 we're about overdue for that, aren't we?

23:07 luckily it was about flattening nested lists

23:07 kiras: lol

23:08 although, now that you mention it...

23:08 danlarkin: but... but.. everyone /knows/ the problem with lisp is the parens!

23:21 technomancy: clojurebot: botsmack is <reply>clojurebot evades successfully!

23:21 clojurebot: c'est bon!

23:22 technomancy: that way it'll randomly choose between the two, right?

23:22 ,botsmack

23:22 clojurebot: java.lang.Exception: Unable to resolve symbol: botsmack in this context

23:22 technomancy: ~botsmack

23:22 clojurebot: Owww!

23:22 technomancy: ~botsmack

23:22 clojurebot: clojurebot evades successfully!

23:22 technomancy: ~botsnack

23:22 clojurebot: thanks; that was delicious. (nom nom nom)

23:24 kiras: lol

23:25 hugod: what is the idiomatic way of going from {:a 1 :b 2} to [:a 1 :b 2] - (apply concat (seq {:a 1 :b 2})) ?

23:28 carkh: why the seq call ?

23:28 (apply concat {:a 1 :b 2})

23:28 dnolen: ,(into (apply concat {:a 1 :b 2}))

23:28 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$into

23:28 dnolen: ,(into (apply concat {:a 1 :b 2})))

23:28 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$into

23:28 carkh: ,(mapcat identity {:a 1 :b 2})

23:28 clojurebot: (:a 1 :b 2)

23:28 technomancy: ,(read-string (apply str (replace {\{ \[ \} \]} (pr-str {:a 1 :b 1}))))

23:28 clojurebot: [:a 1 :b 1]

23:28 technomancy: (just kidding)

23:28 dnolen: ,(into [] (apply concat {:a 1 :b 2}))

23:28 clojurebot: [:a 1 :b 2]

23:28 dnolen: erge

23:29 carkh: ,(vec (apply concat {:a 1 :b 2}))

23:29 clojurebot: [:a 1 :b 2]

23:29 dnolen: does vec use transients?

23:30 carkh: i don't know, look at the source =P

23:30 ~def vec

23:30 not very telling

23:31 dnolen: doesn't look like it.

23:31 i think (into [] ...) is the expected pattern for converting things back to vectors quickly

23:31 hugod: thanks all, I can go back to my glass of wine now

23:32 technomancy: as long as you haven't had enough to take my suggestion seriously =)

23:33 hugod: enough to have trouble typing it, even if I did

23:36 technomancy: what exactly is the point of the cons class?

23:36 ~(list? (cons 1 (cons 2 nil)))

23:36 clojurebot: Huh?

23:36 technomancy: ,(list? (cons 1 (cons 2 nil)))

23:36 clojurebot: false

23:36 technomancy: ,(list? (cons 1 nil))

23:36 clojurebot: true

23:36 technomancy: this boggles me

23:37 hiredman: you use cons to build lazy seqs

23:37 technomancy: it's also used in some other places

23:37 if you call a macro inside a macro, some of the code comes through as conses instead of lists

23:38 hiredman: sure

23:38 syntax-quote tearing through things

23:39 technomancy: I guess all that to say: never use list?, because it will betray you

23:39 since it doesn't return true for some kinds of lists

23:39 (conses and lazy seqs)

23:39 hiredman: ,(doc list?)

23:39 clojurebot: "([x]); Returns true if x implements IPersistentList"

23:40 technomancy: sure, but conses and lazy seqs are both persistent lists

23:40 they're just not Persistent Lists

23:40 hiredman: *shrug*

23:41 technomancy: seems like a leaky abstraction

23:42 hiredman: ,(doc list?)

23:42 clojurebot: "([x]); Returns true if x implements IPersistentList"

23:43 hiredman: IPersistentList is Counted

23:43 they are not lazy

23:44 technomancy: I guess conses aren't counted either

23:45 hiredman: right, and the tail of a cons maybe lazy or not

23:45 technomancy: I just can't think of any situation in which you'd care about IPersistentList over listiness

23:45 since we've already got counted?

23:46 hiredman: shrug*

23:47 technomancy: hiredman: dude, shrug* is for internal use only.

23:47 dnolen: is it possible to check if something is lazy?

23:47 hiredman: hey, I having three conversations here, and I don't even have an stm

23:48 jcowan: How can you be sure you don't?

23:48 technomancy: dnolen: if it's a seq?, it's not counted?, and it's not a cons it might be lazy

23:48 or it might be some crazy new seq somebody reified out of thin air

23:49 jcowan: Huh. The topic hasn't changed since *I* set it two years ago? Wow.

23:49 hiredman: no ops

23:50 tomoj: coi ui doi jy

23:50 didn't know you were involved

23:50 technomancy: jcowan: yeah, I think we've all been waiting for you to return =)

23:50 jcowan: I was back then. Haven't been for a long time, thinking about getting involved again.

23:50 * jcowan laughs.

23:50 dnolen: jcowan: it's a whole different world now.

23:51 technomancy: dnolen: well, mostly. there's still no canonical shell script. =)

23:51 other than that it's all rainbows and unicorn marshmallows though.

23:51 oh, and people still get confused by contains? I guess.

23:52 tomoj: I never hear people complaining about tail recursion

23:53 jcowan: Perhaps that will be my contribution, then. :-)

23:53 tomoj: I wonder if it's bad that I never find myself wanting it

23:53 technomancy: there is a build of openjdk 7 that enables it IIRC

23:53 if I were really bored I would try to hunt that down

23:53 jcowan: It's a way of thinking. If you don't have it, you don't miss it.

23:54 dnolen: you also have laziness which lets you do a whole other set of interesting recursive tricks.

23:54 jcowan: Quite so.

23:54 And if you want both, then there's *shudder* Haskell.

23:55 tomoj: hah

23:57 technomancy: ok... riddle me this then: why does PersistentHashMap use Util.equals instead of Util.equiv

23:57 since it looks like Util.equiv behaves sanely in the presence of longs vs ints, etc

23:57 dnolen: it's finally beginning to dawn on me the ridiculous power of persistent data structures + dynamic typing, now I want them everything.

23:57 hiredman: because PHM implements j.u.Map

23:58 technomancy: ,(clojure.lang.Util/equals 1 (long 1))

23:58 dnolen: everything -> everywhere

23:58 clojurebot: false

23:58 hiredman: and the contract for j.u.Map's .equals is not the same as Util.equiv

23:58 technomancy: ouch

23:59 how can they fit so much awesome into such close proximity with so much bustedness?

23:59 tomoj: wow

23:59 technomancy: the JVM is amazing

23:59 tomoj: I never realized that

Logging service provided by n01se.net