#clojure log - Apr 21 2010

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

0:00 Borkdude: How do I put a type annotation on a function, just for the sake of example?

0:01 I mean, for the return type

0:06 _ato: Borkdude: (defn #^String foo [] ...)

0:08 Borkdude: _ato, txn

0:08 tnx I mean

0:16 _ato and in a let?

0:18 _ato: (let [#^String foo (blah)] ...) I think

0:18 you can probably type-hint either the variable or the expression actually and it'll propagate it

0:20 Borkdude: _ato, I tried this: (let [#^String n 3] n)

0:20 but it doesn't complain about 3 being a non-string value

0:20 _ato: type hints never complain

0:21 they're just hints to allow the compiler to optimize the common path

0:21 it's still dynamically typed, it doesn't do type checking

0:22 Borkdude: I see

0:23 _ato: if you want to check whether its working, turn on *warn-on-reflection*

0:23 Borkdude: how do I do that from the repl?

0:27 _ato: (set! *warn-on-reflection* true)

0:27 joshua-choi: Borkdude: (set! *warn-on-reflection* true) or (binding [*warn-on-reflection* true] ...)

0:27 Dang

0:27 _ato: :)

0:28 cheezey: er. does clojure not have a push function or similar for a stack? o_O

0:30 hiredman: conj

0:31 cheezey: ya i just found that loL

0:31 why wouldn't it be called push? :\

0:31 joshua-choi: cheezey: Because it doesn't always push. conj adds to the from for lists and seqs, but in the back for vectors.

0:32 somnium: because its hard to make push into a clever pun on cons

0:32 hiredman: what would push do differently than conj??

0:32 joshua-choi: s/front/front

0:32 Augh

0:32 s/from/front

0:32 _ato: and 'push' usually tends to imply a mutable datastructure

0:32 cheezey: oh that's weird.

0:32 well so does pop but that's in there

0:33 joshua-choi: ,(doc pop)

0:33 clojurebot: "([coll]); For a list or queue, returns a new list/queue without the first item, for a vector, returns a new vector without the last item. If the collection is empty, throws an exception. Note - not the same as next/butlast."

0:33 _ato: hmm, guess so

0:33 joshua-choi: Right. Never mind then. :P

0:33 conj is short for "conjoin".

0:33 Rich Hickey just decided to name it that. :)

0:34 cheezey: >_> im sure this has messed up more than just me

0:34 Borkdude: _ato, I was thinking set-something, but then I thought, a root binding of a var can't be changed

0:34 joshua-choi: cheezey: On what? What conj is called?

0:34 Borkdude: so what kind of thing is *warn-on-reflection* if it's not a var?

0:34 joshua-choi: Borkdude: It is a var.

0:34 cheezey: joshua-choi: yeah :x

0:35 Borkdude: joshua-choi: so how come I can change it's binding?

0:35 cheezey: i guess i asked you guys a bit early since i found it like 30 seconds after asking but stilllll

0:35 _ato: Borkdude: *warn-on-reflection* is a thread-locally bound var

0:35 which can be set

0:35 (but it only affects the current thread)

0:35 joshua-choi: cheezey: I believe it's because that's what the previous Lisps, Common Lisp and Scheme, called it. I think.

0:35 Borkdude: Vars are actually mutable.

0:35 Very rarely

0:35 And for very specific reasons

0:36 Borkdude: joshua, mutable on thread-level you mean?

0:36 joshua-choi: Vars whose names are surrounded by *'s are "allowed" to be mutated by the user.

0:36 Yeah.

0:36 It's still thread-safe

0:36 But it can get annoying

0:36 Which is why it's rare, as it should be

0:36 There are certain useful things that it makes possible

0:37 Borkdude: is my repl only one thread, since I am allowed to change it to true and it stays true the next time I do something from the repl?

0:37 joshua-choi: I believe so.

0:37 Unless you call something that initiates another thread.

0:38 pmap, for instance.

0:38 Borkdude: joshua-choi, function calls initiate threads I thought

0:39 joshua-choi: Mmm, I don't think so; not unless that function calls something that does create another thread.

0:39 Of course, that's the current state.

0:39 JVM and CPU improvements in the future may eventually make all functions use their own thread

0:39 Borkdude: ah, but I can change a var with a binding in a function, so is that another thread, or how am I supposed to look at this?

0:39 joshua-choi: But right now, there's little point in doing that

0:40 Good question. This is something that I still don't get completely, because I have never needed to think about it

0:40 I can tell you that the binding does *not* create a new thread. Just a new scope.

0:40 I don't know what happens if you create a new thread inside a binding form.

0:40 hiredman: warn-on-reflection is compile time

0:41 joshua-choi: Yes, that's also a good point

0:41 hiredman: bindings are thread local

0:41 _ato: if you create a new thread inside a binding the new thread will see the root value

0:41 hiredman: compilation happens on the repl thread (the place where eval is called)

0:41 joshua-choi: hiredman: Okay, I figured as much.

0:41 _ato: it won't see the new value

0:41 joshua-choi: Oops. I mean @_ato.

0:43 Borkdude: I still don't get how this works, maybe I'll ask it on StackOverflow some time, not much time left now, gotta go to work...

0:44 joshua-choi: Borkdude: Ask again here sometime anytime

0:44 Borkdude: joshua-choi: tnx

0:46 joshua-choi: _ato: What is the purpose of binding's thread-local behavior? It may be surprising for functions in new threads inside a binding to see another value of a var.

1:26 cheezey: if im using (cond ...), and i want to do kind of an "else" statement, would i just evalulate everything else and then put "true (function ...)" at the end? or is there some other way to do this

1:27 Chousuke: that's the way, but use :else instead of true

1:27 it's more idiomatic

1:28 cheezey: Chousuke: thanks, what exactly does :... do?

1:28 Chousuke: :foo things are just keywords

1:28 evaluate to themselves

1:29 ,:foo

1:29 clojurebot: :foo

1:30 Chousuke: the trick is that in a boolean context keywords (as anything not false or nil) have a true value

1:31 you could use :otherwise or :boring if you wanted but :else is the convention :P

1:32 cheezey: ya

1:32 _ato: joshua-choi: I think it's because threads can't tell who their parent is, so they can't inherit (at least efficiently anyway)

1:33 joshua-choi: I see

1:33 _ato: that's what I've always assumed anyway, I could well be wrong ;-)

1:36 cheezey: this is probably the wrong way of thinking about functional programming, but i want to call two functions... how would that be done

1:36 joshua-choi: On a single object?

1:36 cheezey: nope

1:37 lol i am bad at fp. D=

1:37 Chousuke: call two functions in which way? :/

1:37 joshua-choi: Elaborate a litte...do you mean just (a) (b)?

1:37 cheezey: yeah

1:37 Chousuke: you can just call them.

1:37 joshua-choi: You can just do that in most cases.

1:37 Always when you're not within a form.

1:37 cheezey: well it's part of (cond ...)

1:37 clojurebot: CL conditions is http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

1:37 joshua-choi: Ah.

1:37 Chousuke: then use (do ..)

1:38 though generally calling more than one function in a cond means you have side-effects :)

1:40 cheezey: which is bad in fp right =\

1:40 joshua-choi: It depends, but they should be isolated.

1:40 Chousuke: That might be okay in your case but it's always good to consider whether you're needlessly mixing side-effecty code with code that could be pure

1:40 eg. do you have printing out the results mixed with calculating the results?

1:41 cheezey: im still wrapping my head around the whole thing so i guess this is gonna be a slow and painful transition

1:41 joshua-choi: Do you understand what a side-effect is?

1:41 cheezey: changing of state?

1:42 Chousuke: in general, any action which changes behaviour depending on factors outside the function

1:42 joshua-choi: Changing of state is one example

1:42 Other examples: printing messages, writing to a file, connecting to the Internet

2:53 LauJensen: Hey Crew

2:54 zmila: yes, sir

4:11 Licenser_: morning

4:24 tomoj: does a deftype sound good for a triple of doubles that you're going to iterate over?

4:25 i.e. (iterate f the-3d-coord)

4:25 they get fast method dispatch, but it'll box and unbox, right?

4:27 oh, they can be primitive, huh

4:27 hoeck: tomoj: yes

4:28 tomoj: what's the type hint for primitives look like?

4:28 #^double ?

4:28 hoeck: (deftype Point [#^int x, #^int y])

4:28 tomoj: cool, thanks

4:29 hoeck: just like normal typehints

4:29 Licenser_: hmm it seems that c.c does not depend on clojure itself in the jar o.O that leads to odd things

4:29 I talk about the maven artifacts

4:30 which leads to a situation where the dependency resolver of maven

4:30 / lein

4:30 gives you clojure-1.2 and c.c-1.1

4:32 tomoj: I depend on both

4:32 you're getting c.c-1.2 AND c.c-1.1?

4:33 Licenser_: tomoj: nono I juist get c.c-1.1 but c-1.2

4:33 but c.c-1.1 should depend onc c-1.1 in my oppinion

4:33 tomoj: you don't depend on c-1.1 explicitly?

4:33 I always have both

4:33 Licenser_: no

4:34 http://github.com/Licenser/clj-sandbox/blob/master/project.clj

4:34 that is what I do

4:35 tomoj: huh, what does that do?

4:35 oh, defer to the dependency resolver?

4:36 now I see what you mean

4:36 Licenser_: it tells maven that I want clojure <= 1.2 and >= 1.1

4:40 _ato: http://build.clojure.org/releases/org/clojure/clojure-contrib/1.1.0/clojure-contrib-1.1.0.pom

4:40 seems to specify it there

4:41 I'm not sure how maven picks the versions when you give it a range

4:44 Licenser_: _ato: you'

4:44 re right iot does

4:44 I didn't expect maven to be odd here :P (oddly enough)

4:47 bsteuber: Licenser_: Without any conflicts, Maven dependency resolution should be fairly straighforward

4:48 but with conflicts, it uses some sort of "nearest wins" policy

4:52 Licenser_: bsteuber: but [1.1,1.2] and "1.1.0" should not be a conflict

4:52 it should resolve to 1.1.0

4:52 and then it should clojure itself to be forced 'down' to 1.1.0 too

4:52 or it should at least whine 'i can't have this'

4:53 bsteuber: maybe some other dependency requires clojure 1.2?

4:54 or you can check it it whines with -X

5:03 cYmen: sattvik: Do you have a couple of minutes to help me install the hg version of vimclojure?

5:18 LauJensen: For those of you who followed the recent 'Similarity' post from Codemonkey I've tried to add to more shades to the picture here: http://www.bestinclass.dk/index.php/2010/04/clojure-scala-similarities-twins-separated-at-birth/

5:18 sexpbot: "Clojure &amp; Scala Similarities???Twins separated at?birth? | BEST IN CLASS"

5:27 esj: LauJensen: I've got as far as "This is exciting, so lets have a look!" and am already in fear...

5:27 LauJensen: Fear of what?

5:28 esj: a very polite evisceration

5:28 LauJensen: Not at all

5:29 esj: i'm still reading...

5:30 LauJensen: But Stephan concludes that the differences between Scala and Clojure are only syntax, and I think its too important to not voice an oppinion about, since some people are bound to trust in what he says. So this post is just my angle on the very same bullets. And if anybody here agree/disagrees with anything - Just add it to the comments

5:31 esj: I ilke the post it cuts to the relevent points

5:32 LauJensen: Glad to hear it

5:35 bendlas: hi, folks

5:36 esj: yo

5:57 sattvik: cYmen: Sure, I'll help as much as I can.

5:59 cYmen: So, first things first. Apparently there is a nailgun server in the repo in src/main/java/com/martiansoftware/nailgun

6:00 I'm not sure how to set my classpath so I can run it..

6:01 sattvik: Did you compile your own nailgun server instead?

6:02 sattvik: cYmen: If you build vimclojure, it is automatically included in vimclojure.jar, I believe.

6:03 cYmen: sattvik: OK. I have a big issue with building, too.

6:04 The readme talks about adding things to my build dependencies but I'm not sure what it's talking about.

6:04 carkh: i'm trying to set paredit up with clojure mode, but it won't automate the curly-braces {}

6:04 cYmen: It doesn't seem to make sense to add anything editor specific to a project so I don't know what to do.

6:04 carkh: any idea ?

6:04 cYmen: And it doesn't come with a build.xml for ant anymore.

6:05 sattvik: cYmen: Hmmm... let me look into that.

6:06 cYmen: Yes, you'll need gradle to build VimClojure now.

6:06 * cYmen looks for gradle.

6:07 _ato: carkh: make sure your using paredit version 22 (beta) http://mumble.net/~campbell/emacs/paredit-beta.el

6:07 carkh: ahh thanks

6:09 sattvik: cYmen: Just checked the latest readme. It seems like he's discouraging building VimClojure from source, and instead importing it in via your build tool.

6:09 carkh: _ato: it's working, thanks

6:10 raek: _ato: thanks! I've been looking for that too

6:10 cYmen: sattvik: And how would I import that? That clojars url doesn't seem to exist.

6:12 sattvik: cYmen: You can try version "2.2.0-SNAPSHOT", though I don't know which one is considered to be an official release.

6:13 raek: hrm, this didn't solve the curly braces problem for me...

6:15 cYmen: sattvik: Where did you find that?

6:15 sattvik: cYmen: Hmm... Off-hand, I'd say that the readme is intended for once VimClojure is released. I don't think there is an official VimClojure snapshot on clojars.

6:16 cYmen: I just searched clojars for 'vimclojre'.

6:20 LauJensen: Clojure is #12 on Hacker News :) ... and #26

6:22 sattvik: cYmen: So, I'm not sure how well any of those work. You may want to try building using gradle. He used to have a procedure for that in the README, but it seems like he has gotten rid of it. I imagine he got tired of people asking him to move back to Ant.

6:22 LauJensen: sattvik: The guy who wrote VimClojure is also the one who wrote Clojuresque, the Gradle plugin

6:22 I imagine you hit 'gradle build' and thats it :) Otherwise, check for tasks in build.gradle

6:24 cYmen: hmhm clojuresque hm..gradle hm...damn I've never used any of this!

6:25 sattvik: LauJensen: Yes, he is. It's rather annoying though. I understand his point, he does not want to support multiple build systems and Gradle/Clojuresque is his preferred build tool. However, hardly anyone else uses it.

6:26 LauJensen: Hardly anybody uses Clojure compared to C++, but thats not really an argument which says anything about quality

6:26 Besides, he's been good enough to put up at least 3 blog posts showing the ropes of Clojuresque, and its not exactly rocket science :)

6:26 raek: yay! got curlies to work in paredit

6:27 anyone else had to add this to yout .emacs? http://gist.github.com/373669

6:28 carkh: i just followed ato's advice and downloaded betta paredit, works wonder in clojure-mode it seems

6:28 raek: I had the beta paredit and the latest clojure-mode...

6:28 carkh: strange =/

6:28 raek: anyway, it works for me now, so I'm happy

6:29 LauJensen: raek: Thanks for sharing!

6:29 Uuuh, #3 on Hacker News now :)

6:29 sattvik: LauJensen: Well, there is a trade-off to be made. Perhaps Gradle and Clojuresque are excellent tools, but having yet another build tool on top of all of the others makes it more difficult for it to be included in Linux distributions and the like.

6:30 cYmen: as usual there are a million tools for the job

6:30 and hopefully at some point a handful of clever people will get together and build $THE_STANDARD

6:30 LauJensen: sattvik: Sure, but who says lein is the right choice? People like it because its fun to stay Lispy and the fact that its so easy, but Gradle is vastly more mature and integrated into the rest of the Java ecosystem ...

6:33 cYmen: Will I need cojuresque to build vimclojure with gradle?

6:34 LauJensen: I suspect its added as a dependencies to the build file itself, so probably not

6:34 If you build Clojureql, it will first fetch clojuresque and load it, then fetch CQLs dependencies and build

6:34 (clever)

6:35 cYmen: I'm confused. But gradle build just says that the plugin with the id clojure is not available.

6:35 sattvik: LauJensen: I am not arguing that lein is better, though I do appreciate the Lispiness. I am just saying Gradle is fairly unknown, not just in the Clojure community but in Java as well. Java is dominated by Ant and Maven.

6:35 cYmen: I'll read the gradle tutorial. *sigh*

6:36 LauJensen: cYmen: check out Meikels blog - I'm sure he's commented on it somewhere

6:36 (sure = I imagine so)

6:36 cYmen: :)

6:36 LauJensen: sattvik: Fairly unknown??? :) I think you'll be hard pressed to back that up with facts

6:38 cemerick: There are no facts when it comes to language and tool debates. Only innuendo and relative volume.

6:38 sattvik: cYmen: Try http://gist.github.com/373685

6:38 LauJensen: Anyway - I cant decide which is better in the long run. But Clojuresque is great and in its own niche, so is lein. I just think you should give both a shot and learn them before dismissing either

6:38 cemerick: and emotion, dont forget :)

6:39 sattvik: cYmen: Note that it doesn't build the nailgun part, just the VimClojure part. You can either modify it or use a plain old nailgun 0.7.1 jar.

6:39 cemerick: right, so we have innuendo, relative volume, emotion, and ego. For sure, technical details will work themselves out somewhere...

6:40 LauJensen: hehe, feeling a little sarcastic this morning Chas? :)

6:41 sattvik: LauJensen: Well, I haven't worked with Groovy at all, so in over a decade with working in Java, I hadn't heard of Gradle until VimClojure started using it.

6:41 cemerick: Yeah, it's hard to say that gradle is a common tool outside the groovy world. *shrug*

6:41 LauJensen: Ok

6:41 cemerick: LauJensen: Eh, no, pretty sincere in that last one. Between the build tool and editor foodfights, and the absurd clojure vs. scala discussions and articles, I'm not too optimistic in general.

6:42 vegai: I wonder if this is a faq...

6:42 LauJensen: cemerick: Im sorry to hear that. But on a positive note I've rectified some of the misconceptions about scala=clojure

6:42 cemerick: Someone older than I will likely pop up now and say, "Uh, so what else is new?"

6:42 vegai: what do I do wrong if my helloworld built with lein jar tells me

6:42 vegai@mab:~/src/test$ java -jar hellotest.jar

6:42 Exception in thread "main" java.lang.NoClassDefFoundError: hellotest

6:43 Chousuke: I think equating scala with clojure in any way is somewhat of a mistake. they're completely different languages :/

6:44 vegai: it seems to me that java, scala and clojure are quite nicely analogous to C, C++ and common lisp

6:44 Chousuke: I mean, no-one's equating Clojure with haskell

6:44 LauJensen: Chousuke: which is weird, as they have more in common that clojure/scala

6:45 Chousuke: LauJensen: yes.

6:45 vegai: well, scala does have more haskelly typing, doesn't it?

6:45 LauJensen: But I think most Scala users actually perceive that Scala is a lot more like Haskell than Clojure is

6:45 vegai: uhm, sorry. Logical mistake on my part.

6:45 eevar2: clojure is closer to scheme, tho? (I only know cl)

6:45 LauJensen: I wouldn't say so, no

6:46 (chousuke would)

6:46 Chousuke: yes :P

6:46 but in the end, any such comparisons are only good for a quick approximation

6:47 cemerick: Chousuke: it's that caveat that no one seems to have considered, never mind internalized.

6:47 * eevar2 did shoot for haskell rather than scala

6:47 cYmen: sattvik: Is that an ant buildfile?

6:48 Chousuke: cemerick: unfortunately :/

6:48 sattvik: cYmen: Yes.

6:49 cYmen: sattvik: The error messages start with [javac] /Users/simon/code/clojure/vimclojure/src/main/java/vimclojure/Nail.java:30: package clojure.lang does not exist

6:49 I haven't worked with ant so...

6:52 sattvik: cYmen: You need to jars for my build.xml to work. Clojure.jar and nailgun.jar. It's probably easiest to copy them into a 'lib' subdirectory of your VimClojure.

6:53 cYmen: sattvik: I'll try to figure out gradle and if it doesn't work in about an hour I'll try your script again.

6:53 Need to focus on something for now.

6:53 sattvik: cYmen: no problem.

6:59 cYmen: Wow..building the hello world example with gradle takes 2.4 seconds

7:22 lessthantristan: is their some better way of doing: (apply -> (cons {:a {:b {:c 1}}} '(:a :b :c))) (which doesn't work)

7:24 of course, the desired result is: (-> {:a {:b {:c 1}}} :a :b :c)

7:24 raek: lessthantristan: can you give an (possibly mock-) example of what data you have and what data you want

7:24 ah, ok

7:24 you cant apply -> since it's a macro

7:25 so that's why it doesn't work

7:25 maybe you could use get-in

7:25 ,(get-in {:a {:b {:c 1}}} [:a :b :c])

7:25 clojurebot: 1

7:26 lessthantristan: yes! that's exactly what i was looking for

7:26 thanks raek :)

7:28 raek: there's also assoc-in update-in and dissoc-in (the last one is in clojure.contrib.core, though)

7:36 lessthantristan: also, apply can take additional args before the argument list

7:36 (apply f 1 2 [3 4 5]) can be seen as (apply f [1 2 3 4 5])

7:37 ,(doc apply)

7:37 clojurebot: "([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."

7:51 LauJensen: netsplit, or just me?

7:52 noidi: [14:51] >>> Signoff LauJensen: #clojure (Remote host closed the connection)

7:54 LauJensen: kthx

8:07 cemerick: LauJensen: nice post (the separated at birth one)

8:08 LauJensen: cemerick: Thanks a lot

8:08 cemerick: I don't really agree with the OO point though.

8:08 (a remarkably minor difference, of course)

8:09 LauJensen: You don't agree that Clojure is not Object Oriented?

8:10 cemerick: It's not Java-style Object Oriented, no. But given its strong interop with existing object hierarchies, and full embrace of interfaces, it's not not OO. :-)

8:11 LauJensen: I disagree, I think its not not not OO, but it interops with an OO language

8:12 cemerick: Question then: is javascript OO?

8:13 LauJensen: I would say so

8:13 cemerick: OK, that's interesting. I thought you might have been falling into the trap of thinking that only Java/C# OO qualifies. :-)

8:15 LauJensen: No - And my point was more relating to Richs explanation of the link between state and OO, which was why I linked the rationale. OO architecture is in no way encouraged by Clojure

8:15 rhickey: cemerick: if OO is about unifying state and identity, then Clojure isn't OO. If OO isn't about that, in what way is Haskell not OO?

8:16 Of course, OO is a spectrum, as long as Javascript and Java are both OO, but I wonder if, after you've pulled it apart as Clojure has, it is still useful to call it OO

8:17 fogus: rhickey: What would you call it otherwise?

8:17 rhickey: CLOS showed OO wasn't about having the polymorphic methods inside the classes

8:18 fogus: abstraction-oriented?

8:18 cemerick: I won't bother trying to talk intelligently about haskell. :-)

8:18 fogus: oooooo. I like that

8:18 cemerick: However, insofar as you can associate methods with types (protocols and records), I'd say clojure is a flavor of OO.

8:19 rhickey: cemerick: Haskell type classes do similar things

8:19 cemerick: Or, it provides for a flavor of OO.

8:19 It's entirely possible that between Java, C#, javascript, smalltalk, and perhaps clojure and haskell, the term has lost all real meaning.

8:20 fogus: cemerick: I think that's more likely

8:20 rhickey: cemerick: I'm not sure. I think when you look at all the flavors of things called OO, and separate all the differences, the one thing that remains is having an object that can change over time

8:20 cemerick: rhickey: so a Java class with all final fields isn't OO?

8:21 rhickey: cemerick: no

8:21 cemerick: Heh, that's ballsy. :-)

8:21 rhickey: it's not any more OO than a Haskell type, a C struct etc

8:21 LauJensen: I was expecting some dancing around the answer, not just a 'no' :)

8:21 _ato: I don't think basing your definition on what corner-cases and what "can" be done is particularly meaningful, such arguments generally just deteriorate into "well, everything's turing complete".

8:21 fogus: rhickey: Is there a precedent for abstraction-oriented programming? Or is it a confluence of different ideas?

8:21 _ato: "oriented" is a fuzzy word

8:22 rhickey: fogus: good OO is abstraction oriented

8:22 cemerick: Isn't "abstraction oriented" an even worse term? C is abstraction oriented too. :-/

8:22 rhickey: Haskell with type classes is abstraction oriented

8:22 cemerick: what language constructs in C embody abstractions?

8:23 i.e. let you name and circumscribe them?

8:24 * fogus needs to re-read Thompson's Haskell book

8:24 bsteuber: preprocessor macros lol

8:24 cemerick: rhickey: for loops are an abstraction over jumps.

8:24 * cemerick is being a PITA on purpose

8:25 cemerick: I'm just saying, "abstraction" isn't exactly less overloaded than "object".

8:25 rhickey: interestingly, prototype-based OO is not particularly abstraction oriented

8:25 _ato: but loops are an abstraction defined for you, you (as the programmer) aren't the one defining them

8:25 rhickey: cemerick: right, all terms are overloaded, yet still meaningful and useful

8:25 fogus: rhickey: Not being terribly familiar with Haskell type classes I'm not sure how/if Clojure's model differs

8:26 rhickey: but clearly, Smalltalk/C++/Java style OO combines abstractions in the forms of classes/interfaces with mutable objects. The mutable objects aren't the abstractions

8:27 fogus: Clojure's deftype + protocols are akin to a dynamic version of type classes, minus some things type classes can do that require the type system

8:30 The key question is, when you re-assemble all the pieces in Clojure, taking an instance of a datatype, that implements one or more protocols, and put it in a reference type (giving it identity), is the resulting thing an object? If not, how do they differ? What presumptions of objects that people have will be violated?

8:30 cemerick: I'm still hung up on this objects-imply-mutability concept. I've got defrecord, where I define a set of fields and particular implementations of operations over those fields which are tied only to instances of the defined class. That looks, smells, and acts like objects I've used for the past 10 years.

8:31 rhickey: cemerick: it certainly doesn't, insofar as you have no identity without adding a reference around it

8:32 cemerick: It's amazing how much one can get done in this field without having a thorough grasp of core concepts.

8:32 rhickey: cemerick: Haskell type classes give you defined sets of fields, functions that operate over those fields, tied to instances of the type. No identity, no object in sight

8:34 I am interested in what it would take to reassemble objects using Clojure constructs in a way that did state/identity correctly and still felt like an object to someone coming from, e.g. Java

8:35 LauJensen: rhickey: The 'are we there yet' left me with the impression that it would be impossible

8:35 rhickey: (rebuilding objects by making every field a reference doesn't count)

8:35 LauJensen: that talk ended with this as an open question

8:35 LauJensen: I remember

8:36 rhickey: x.foo(y. z) ==> (alter x foo y z ?)

8:36 Licenser_: rhickey: I think thgat will be hard, most people associate objects with mutability/changing state

8:38 rhickey: Licenser_: but Clojure offers a recipe that does just that. It just adds the ability to say @object and get a value

8:39 Clojure says, objects have values

8:39 LauJensen: rhickey: If thats all, why isnt building objects with every field a reference good enough ?

8:39 Licenser_: I know but I'm not sure if it will be easy to wrap all that in a form that it feels natural to a java person

8:39 rhickey: LauJensen: because the resulting object can't present itself as a value

8:40 or rather, I contend (via Clojure)

8:41 Licenser_: hmm well how about a ref that holds a map

8:41 rhickey: Licenser_: yes, that's what we do in Clojure instead of objects

8:41 Licenser_: then changing the object would be just derefferencing it, altering it and fine

8:41 LauJensen: Ok I see - So all function application on the object should be in sync with all of its fields , like the entire thing was transactional

8:42 Licenser_: I think the main thing that makes objects different from maps is that they hold functions that work on themselfs while objects usually don't

8:42 sattvik: rhickey: Yes, a record in a ref is about as close as an answer I can think of. Granted, I am not sure that gives you quite all of the things OO promises Java programmers. One could argue that records fail to encapsulate properly.

8:43 rhickey: That's the argument I make against STM as something you could throw over existing mutation-oriented code - the only time you could see a consistent value of an object would be inside a transaction

8:43 cemerick: rhickey: if the criteria is familiarity to a Java programmer, then I still maintain that a record instance fits the bill. That becomes more and more true as mutability leaks out of a lot of APIs.

8:43 Licenser_: well we could make a simple way to do stuff like (alter x (@x function) params)

8:43 LauJensen: Ah yes, I get it now

8:44 _ato: rhickey: So the point is that in Clojure's model objects *have* values, but aren't *themselves* values? And thus how would we map this back into a java-like language naturally. The main difficultly being how to make Clojure's deref -- grabbing the value of an object, vs calling a method and altering the object to a new value concept seem natural in such a language?

8:44 rhickey: cemerick: really? how could you model the simplest OO-like collection for a Java programmer given only an immutable instance?

8:45 cemerick: rhickey: have "mutating" methods return new values. Lots of Java-only APIs do this as a matter of course.

8:45 rhickey: _ato: It goes to what cemerick and I are discussing - is a record instance an object, or a reference + record instance?

8:45 cemerick: rhickey: that obviously doesn't address anything you'd like to solve w.r.t. identity, but it "feels" just fine to a Java dev.

8:46 rhickey: cemerick: you've been working in some alternate universe of functional Java, where no one uses java.util collections?

8:46 cemerick: (as long as you can convince them of the efficiency of it all, though that's less and less a problem.)

8:47 rhickey: not alternate, but many, many shops and projects are adopting immutable libraries such as google collections.

8:48 and others are producing APIs that avoid mutability as well

8:49 rhickey: so here's an example of a hybrid using Clojure's approach - a concurrent hash map that can only be changed in a transaction http://github.com/richhickey/clojure/blob/master/src/jvm/clojure/lang/TransactionalHashMap.java

8:50 cemerick: without some MT-safe place to put/access the return values, immutable APIs/objects are insufficient

8:51 sattvik: cemerick: Perhaps some people are doing it, but I doubt it is considered a norm. I'd argue that the standard in things like Java EE is mutability.

8:51 fogus: rhickey: It seems fundamentally at odds to "do state properly" while maintaining something that a j.u.c Java programmer would recognize.

8:52 ... feel comfortable with that is

8:52 cemerick: rhickey: That's a tougher hill to climb. STM is far, far harder sell than immutability to a Java mindset.

8:53 rhickey: fogus: I'm not sure about that. If a reference to a record is our object, one would just need a way to funnel 'mutating' methods to alter, and accessors through deref

8:53 LauJensen: When it comes to handling of state, the if no virtue in backwards compatability, if that means Java familiarity, imo. The imperative approach is wrong and should be discarded :)

8:53 cemerick: sattvik: Not the norm now, but I think it's likely it will be the norm sooner rather than later.

8:54 rhickey: cemerick: one could have transactional objects, or atomic objects, or async objects, per reference type used

8:54 cemerick: all could be made to feel like x.mutate(y)

8:54 cemerick: In EE-land in particular, where people just throw stuff at a MQ or such to solve parallelization and concurrency issues, etc.

8:55 rhickey: Right, and I'm all for reaching for that, but it's a higher goal that I'm not sure is necessary, at least w.r.t. being able to tick off the "OO checkbox".

8:56 rhickey: cemerick: right, to the extend frameworks create single-threaded apartments, people never need leave their mutable object approach, unles they find values valuable otherwise

8:56 cemerick: Put another way, I'd say it's a decidedly minority viewpoint that immutable "objects" aren't Objects. ;-)

8:56 sattvik: cemerick: That's the problem. In EE-land, the container is there to help you avoid thinking about things like concurrency. Therefore, they do not bother learning how to do it properly.

8:57 rhickey: cemerick: I think until we establish that objects are identity+value we are hopeless. Immutable values are not objects

8:57 fogus: rhickey: That Ref->record model provides fine-grained mutation. Something that j.u.c programmers are familiar with, but is it antithetical to proper state management?

8:57 LauJensen: rhickey: Why this interest in fixing an old model? You've got something that works, why not keep improving and taking that to the next level ?

8:57 rhickey: if they are, then you;ll just have to invent another term for identity + "object"

8:58 cemerick: rhickey: as a formalism? Perhaps. As a language positioning issue, I think that approach will fall on deaf ears, at least until there's a ready-at-hand solution.

8:58 * cemerick put on his marketing cap

8:58 rhickey: fogus: ref->record still always provides access to the full record as a value at any time, so no

8:59 _ato: What worries me is that if you make it seem too familiar and people will see it as the same old model, and not bother to learn the differences between transactional, atomic etc, just make everything really fine-grained atomic (updating field individually) and you're getting back to where you started

8:59 rhickey: cemerick: as a, how then will you package up ref + value and what will you call it. Folding these 2 leaves you with a bigger challenge to come, vs getting it straight up front.

9:00 sattvik: rhickey: Just out of curiousity, why do you say that STM is a barrier for Java people?

9:00 rhickey: _ato: that's a reason to package it up 'the right way' vs people rolling their own. You are right, e.g. see the JRuby wrapping of Clojure's STM that makes every field a ref - completely misses values.

9:00 sattvik: I didn't say that

9:01 fogus: rhickey: Ahhh. So you're changing the read model for them. I guess then that would be familiar since the j.u.c crew tends to think they deal in wholesale reads

9:01 cemerick: rhickey: I don't think you have to package a ref and value to get home. Unless it yields benefits of its own aside from familiarity to these Java devs that aren't happy with immutable objects, I'd consider it a non sequitur.

9:01 rhickey: fogus: there would be a new capability - get the value of an object - that is missing in today's OO

9:02 sattvik: rhickey: Sorry, I misread the message.

9:02 cemerick: Just out of curiousity, why do you say that STM is a barrier for Java people?

9:02 fogus: rhickey: I think I follow now

9:03 rhickey: cemerick: turn it around. Some Java dev says - Clojure looks great - show me the way. I was doing ___ using this mutable object, what's the Clojure way? You'll have to bring up references.

9:04 fogus: rhickey: And is that "get the value of an object" the place where Kafka comes into play?

9:04 cemerick: rhickey: it really, really depends on what ___ is. If it's as simple as an .addFoo or .changeBar method that could just as easily be implemented to return a new value, then you're done.

9:04 rhickey: cemerick: e.g. "I was maintaing a set of logged-in users, accessed throughout my app"

9:04 cemerick: that's just not true. The old object held the result, the new method leaves them wondering where to put it

9:05 mutable object method becomes value + function + place to put the result

9:06 cemerick: rhickey: Again, I'd point at the generation of APIs that are maturing right now that are decidedly value-oriented. That's where the mainstream will be in some small number of years, not decades.

9:06 _ato: just making everything immutable means you're just working with values, ie a pure computation, it misses the identity half of the picture

9:06 rhickey: the entire point of Clojure was that it came with stuff for that last bit

9:07 cemerick: but those APIs just beg the where to put it question

9:08 cemerick: rhickey: Back on the MQ, or in the clustered session state, or whatever.

9:08 rhickey: cemerick: and maybe people will just adopt value + reference as Clojure delivers

9:09 cemerick: If they do, it will constitute a move to value- and abstraction-oriented programming, IMO, and a rejection of objects

9:09 which suits Clojure just fine

9:09 cemerick: exactly

9:09 sattvik: cemerick: I strongly disagree. You cannot change something like how servlets deal with adding/removing to a request or a session in a purely value-driven way without major disruption.

9:11 cemerick: sattvik: I wasn't suggesting that servlet sessions become values themselves -- that's a stateful service, just like writing to disk.

9:11 rhickey: fogus: sorry, I missed your Kafka question, please restate

9:12 cemerick: rhickey: Would you find this "transactional object" concept useful in general, above and beyond what values and reference types get us now?

9:15 rhickey: cemerick: dunno. Using refs explicitly has advantages, in that you tend to get the value out right away in order to work with pure functions. Obviously the combo wouldn't let you do anything you couldn't with the pieces

9:15 cemerick: OTOH, if t helps people conform to their mental model, the combo could have great appeal, essentially ensuring correct use of the constructs

9:16 AWizzArd: Regarding the mental model and OOP: i missed inheritance in the discussion so far.

9:16 rhickey: one problem is how the type of reference impacts the use of the object. Will that become a property of whatever replaces 'new'?

9:17 cemerick: rhickey: I'm all for better abstractions. But I guess I'd say, unless you can answer "yes" to that question, the notion of "transactional objects" might only be searching for a problem to solve.

9:18 rhickey: cemerick: problem to solve - making Clojure less alien to non-functional programmers without simply supplying them their same old broken stuff

9:19 cemerick: rhickey: you may find people coming to you faster and easier than you thought possible. *shrug*

9:19 rhickey: cemerick: as is?

9:19 cemerick: yes, as is.

9:20 As long as you don't say "Clojure isn't object oriented" too loudly. ;-)

9:20 rhickey: cemerick: that's already the case :)

9:20 cemerick: heh

9:20 Chousuke: heh

9:20 I suppose it's better to say what clojure is, instead of what it isn't :P

9:21 cemerick: rhickey: well, you can say "with defrecord, clojure is now OO!!!11!!"

9:21 AWizzArd: cemerick: wouldn't that require inheritance?

9:21 rhickey: cemerick: well, the converse is true also, as people now are starting to say - Clojure has objects, see defrecord + protocols. We'll see if that leaves people satisfied or confused

9:21 cemerick: AWizzArd: I'm speaking from a positioning / marketing standpoint here more than technical.

9:21 AWizzArd: before they had defrecord + protocols they had defstruct + defgeneric

9:22 rhickey: (defrecord Foo [a b])

9:22 (def f (Foo. 1 2))

9:22 (how-do-I-make-fs-b=? 42)

9:22 cemerick: rhickey: honestly, the two make for objects, outside this channel anyway. :-)

9:23 rhickey: cemerick: I don't think so ^^

9:23 I guarantee that will be a common question

9:24 cemerick: rhickey: OK, but then you need to tell people that Strings aren't objects, at which point they'll think you're nuts.

9:24 AWizzArd: is 15 an object?

9:24 rhickey: cemerick: the 'there are non-mutable classes in Java' argument is secondary. People have mutable objects and want replacements

9:25 cemerick: I don't think you can say, it's like Java OO where every class is like String

9:25 people wouldn't use Java if every class was like String

9:25 it's insufficient

9:26 esj: be like a mathematician and define 'immutable object' and 'immutable object oriented' to your liking and proceed

9:26 AWizzArd: Is 15 a value and x in (def x 15) an object?

9:27 cemerick: AWizzArd: If I put my Java hat on and forget what I've learned from rhickey, then when boxed, 15 is an object.

9:27 AWizzArd: hmm

9:28 rhickey: OO is borne of a (valid) desire to make our programs relfect our mental model of the world. Our mental model of the world includes identities. They were baked together with state in OO, but saying all you need is values is a broken replacement

9:28 cemerick: rhickey: I think looking at what's happening in scala is instructive, where almost the entire population is made up of expatriated java devs. Mutability is considered a code smell, and dealt with accordingly.

9:29 rhickey: cemerick: and everyone is using actors for identity? Or just secreting away values in vars and hoping for the best? Or using locks?

9:29 cemerick: rhickey: That's not *all* you need, but I don't think you need this transactional object concept to satisfy a java dev's sensibilities, is all I'm after.

9:30 rhickey: combination of options A, B, and using MQs and such, probably.

9:30 rhickey: cemerick: the transactional bit isn't important, just reference (ref/atom/agent etc) + value

9:30 cemerick: sure, either way

9:31 rhickey: cemerick: MQ's et al have huge problems in requiring object serialization

9:31 cemerick: Absolutely.

9:31 rhickey: vs say, atoms :)

9:31 cemerick: But it's an easy, dumb way to parallelize operations.

9:32 rhickey: cemerick: we're not talking about parallelization, but identity. The set of logged in users

9:32 cemerick: And I'd say you'll have no problem getting people to use an atom properly with a record.

9:33 rhickey: cemerick: looking forward to your help with that :)

9:33 cemerick: rhickey: I do my best. You should have seen this PHP friend of mine take to clojure like duck to water. It was crazy.

9:33 rhickey: cemerick: wow

9:34 cemerick: I don't think immutability is the biggest hurdle by a long shot.

9:34 rhickey: cemerick: what is, IYO?

9:35 cemerick: Realizing, and then, accepting that programming doesn't need to be so bloody complicated.

9:35 rhickey: is that a hard sell? :)

9:35 cemerick: Yes. You'd be surprised.

9:37 People like building up large edifices of *stuff*. Probably mostly out of habit. When I show people, hey, here's a map literal, go reduce it over this stuff here, and you're done, they really can't believe it works.

9:39 * rhickey wants fogus to explain where Kafka comes into play

9:39 * AntonyBlakey Surely you're not attributing the resistance to functional programming and immurability

9:39 AntonyBlakey: just to people wanting to write lots of code?

9:39 Licenser_: rhickey: with the bugs :P

9:40 AntonyBlakey: What about the inherent mutability and (pragmatic) acceptance of identity in our everyday experience of the world.

9:41 Licenser_: hmm is there a ideomatic way to execute some code every n seconds?

9:41 AntonyBlakey: my world is static

9:42 AntonyBlakey: Licenser_: you just need to tune in.

9:42 cemerick: AntonyBlakey: I think the resistance to immutability is rapidly waning.

9:42 Licenser_: AntonyBlakey: I work in a Siemens branch - we are static :P

9:42 sattvik: On the surface, a Clojure hard-sell is considering Lisp ancient or too many parantheses. But that's superficial. I think the real problem is people shifting away from the OO-mindset. There has been a massive investment in OO tools ands methodologies. Retraining programmers to a functional method of programming is a huge hurdle. Granted, it may be inevitable.

9:42 AntonyBlakey: cemerick: That is certainly the case, but that isn't the same as saying that mutability isn't required

9:44 cemerick: AntonyBlakey: And the little corners of mutability that are necessary are well-covered by the reference types.

9:44 AntonyBlakey: I'd contend that the desire for, and use of mutability is related to our physical experiences in a Kantian sense

9:45 So for many problems, the immutable solution requires an additional set of cognitive tools that can act as the ground terms.

9:45 i.e. replacing the analogy of physical boxes that contain things that can be handed to someone else, emptied, filled. And paper that can be written on, erased etc.

9:45 rhickey: cemerick: that's probably the best argument against any combo ref+value object - such things would encourage far more identities than are required (as does OO). One of the best things about delivering them separately is seeing how few identities are needed

9:48 cemerick: rhickey: back to the simplicity aspect. Consider the classic: compare what ants needs to the typical Java impl, and people are stunned.

9:48 AntonyBlakey: One thing I haven't seen so much in clojure is the idea of refs as values that get threaded through computations. Most refs seem to be either root definitions or thread-local bindings. And the thread-local bindings worry me because they require a guarantee that subsequent computation is single threaded.

9:51 Rather than comparison to Java, maybe a productive thought experiment would be to consider the pragmatically irreducable examples of mutability that we experience in the physical world, which then often show up as domain entities in software models.

9:51 rhickey: AntonyBlakey: Clojure is that experiment

9:51 AntonyBlakey: i.e. Refs are like boxes/containers. What is like a piece of paper?

9:52 rhickey: AntonyBlakey: a vector in a reference

9:53 AntonyBlakey: No, thats like putting a piece of write-once paper in a box.

9:53 Chousuke: AntonyBlakey: a written-to paper is not the same as an empty paper

9:53 AntonyBlakey: It misses the essential nature of the physical experience

9:54 But the paper doesn't change. It has identity.

9:54 Chousuke: you can't take the paper out of the box, write to it, and put it back without taking it out of the box

9:54 but you can look at it and do things based on what's on it

9:54 AntonyBlakey: Not the point. I don't have my paper in a box in the real world.

9:54 cemerick: AntonyBlakey: I think someone hasn't seen rhickey's key preso :-) http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey

9:54 sexpbot: " InfoQ: Are We There Yet?"

9:54 Chousuke: AntonyBlakey: well, an envelope then

9:54 AntonyBlakey: a translucent envelope

9:55 AntonyBlakey: Still not right. An accounting ledger gets modified directly. That's the physical relationship people have with the thing.

9:55 Chousuke: yes, but the old "values" of the accounting ledger haven't gone anywhere

9:56 they're in your memory

9:56 as you once saw them

9:56 and you work based on that memory.

9:56 AntonyBlakey: No, you hand the piece of paper to your colleague

9:56 He writes on it.

9:57 Chousuke: yes, because he has a lock on it

9:57 :P

9:57 (he's holding it, preventing anyone else from writing to it)

9:57 mefesto: isn't the piece of paper acting as a ref at the point?

9:57 AntonyBlakey: cemerick: saw it when it came out, I'll rewatch it.

9:57 mefesto: it's a ref with a value that is written on it

9:57 Chousuke: mefesto: I suppose.

9:57 cemerick: AntonyBlakey: The issues you're raising are pretty well hashed out there.

9:58 AntonyBlakey: The point is that we have a physical understanding of the piece of paper as a mutable entity. Consider a piece of cake that you consume.

9:58 cemerick: yes, it's coming back to me as I run it.

9:58 Chousuke: a piece of paper is not mutable.

9:58 mefesto: AntonyBlakey: all you really care about is the value on that paper at any point in time

9:59 AntonyBlakey: If you cut the piece of paper then it's certainly mutated.

9:59 rhickey: http://en.wikipedia.org/wiki/Schrödinger's_cat

9:59 AntonyBlakey: But in any case, 99% of people will say that you write on the piece of paper and change it.

9:59 Chousuke: hm, I think I'm a bit confused now.

10:00 so I suppose it's better indeed to think that the paper is the ref

10:00 AntonyBlakey: My point is the relationship between our fundamental cognitive models as generated my out physical embodiment, and the abstractions we see in the language.

10:00 Chousuke: because it's the thing that's "mutating"

10:00 mefesto: AntonyBlakey: couldn't writting on the paper be thought of as a function and the value of the paper has change ... it's a new thing at that point

10:01 AntonyBlakey: You could force yourself to think of it however you want. But what is the way of thinking about it that matches the model we have by virtue of our embodiment?

10:01 Chousuke: AntonyBlakey: but if you need to work with what's written on the paper, you look at it, form a snapshot of its contents in your brain, and then work on that snapshot

10:01 mefesto: then you have a ref (identity) that expresses it's conceptually the same thing even though the value has changed between fuctions of scribbling on it

10:01 Chousuke: AntonyBlakey: you could never work with a paper that could just *poof* change what's written on it

10:02 AntonyBlakey: You're talking about a granularity that isn't used in the 'real' world.

10:02 Chousuke: AntonyBlakey: and even just following what someone is writing onto a paper is very difficult

10:03 I wonder if we are agreeing or what.

10:05 chouser: AntonyBlakey: I think the natural conclusion to the argument you're making is very similar to existing object-oriented models.

10:05 Chousuke: AntonyBlakey: if you're writing to a paper it's basically the equivalent of executing a function to change the value on the paper

10:05 AntonyBlakey: and when you're done, the function ends and the paper has a new, complete value.

10:06 chouser: that is, fine-grained identities composed together into more and more complex hierarchies (speaking here of mutable objects with fields that are mutable objects, etc.)

10:06 Chousuke: then someone can take a look at it, remember its contents, and do something

10:06 AntonyBlakey: cemerick: and now that I'm seeing Rich's presentation, I remember that the problem I had with it is that it first of all generates an abstraction of reality and then asks how we can model it. The *initial* abstraction is one that breaks the relationship between the world as pragmatically modelled and experienced, and the end-point abstraction. It's not that it's philosophically wrong, but the essential feature that would

10:06 the end-point abstractions understandable (intuitive) has been lost.

10:07 rhickey: AntonyBlakey: what chouser said, and furthermore will thus fail to properly model observation and memory. You can't just model 'change' and think you are modeling the world

10:08 chouser: AntonyBlakey: so if that's what you want, I think you have lots of options to choose between. The question is, are they insufficient in some way that can be fixed without adjusting the mental model you're starting with.

10:08 AntonyBlakey: chouser: but we don't naturally think in those terms, which is my *only* point. Remembering that this discussion was about 'what makes it accessible to java devs'

10:08 rhickey: what we see when we look at paper is a snapshot produced by light reflected from it at a point in time.

10:08 cemerick: AntonyBlakey: Virtually nothing we do in software has anything to do with how we "intuitively experience" the world.

10:08 AntonyBlakey: Personally I like Rich's choices.

10:09 rhickey: that's a reductionist viewpoint. It may be correct, but it's not how people think.

10:09 chouser: Well, then not addressing anyone in particular, I think the general route for any individual is that same question -- are there not weaknesses in how you're currently doing things?

10:10 AntonyBlakey: In the same way that saying "I've having a seretonin induced sense of connection' is *not* the same as "I love you"

10:10 Chousuke: AntonyBlakey: But that's how the real world works: the brain sees discrete values, and is able to connect those together to form a series.

10:10 AntonyBlakey: We dom'

10:11 We don't experience them as discrete values.

10:11 chouser: So if you can show someone complexities they're already dealing with that maybe they thought weren't complex or were unavoidable, and say "we have a way to make that simple", now you've got someone ready to learn.

10:11 AntonyBlakey: This is the point about it being fundamentally Kantian argument about embodiment.

10:11 Chousuke: because the brain forms a "continuous" series from them.

10:11 rhickey: AntonyBlakey: I disagree, it's precisely how we think. We rely on our memories of things not being destabilized by the fact that time is passing, in order to be able to make decisions. And we know those decisions might not reflect 'current reality'. We do it every time we look both ways before crossing the street

10:13 chouser: man, if we could retry street-crossing, we could get a lot more of it done with a lot fewer stoplight-locks.

10:14 rhickey: all models are gross simplifications, but I contend OO ws an oversimplification whose weaknesses we now see clearly in the presence of true concurrency, but not as an inherent limit of our understanding of how we think about things.

10:15 perception and memory must become part of the model, and references + values make that easy and efficient

10:15 AntonyBlakey: I'm not advocating OO, although we may have wandered through that. I'm advocating a model that is congitively based

10:16 Chousuke: Do you have an idea what such a model would look like?

10:17 AntonyBlakey: To make it easier for people to use. You wouldn't want a language that has the same relationship to our thought processes as Quantum Physics i.e. all correct and so on, but impossible to square with reality.

10:17 Chousuke: no

10:17 I'm just trusting in Rich.

10:19 But one point I'd make is that the physical world at our level of granularity isn

10:19 '

10:20 .. isn't thread safe

10:21 rhickey: AntonyBlakey: can two people write on exactly the same part of the paper at the same time?

10:21 AntonyBlakey: So maybe what we are experiencing is the point where software has to 'grow up' and become a real science, and that formal models such as Clojure has are now required.

10:22 vegai: does clojure have formal models really?

10:22 AntonyBlakey: No, but two people can drive into the same car park at the same time. Or attempt to at least. One example of where we don't want to accept real world semantics.

10:22 Chousuke: I never saw clojure's model as "formal". But it does have a model, unlike most languages

10:22 AntonyBlakey: vegai: well it's not exactly Z, but it's a principle approach

10:22 rhickey: Clojure's model is not formal, it is purely intuitional

10:22 Chousuke: the problem is exactly that most languages don't even have a model for this.

10:23 AntonyBlakey: I think Clojure is more amenable to reasoning than, say, Java's memory model.

10:23 rhickey: AntonyBlakey: but two cars can't occupy the same space at the same time either. Physics is dealing with the threads in some sense

10:24 wthidden: Question? Does a (seq of a lazy-seq) retain its laziness?

10:24 Chousuke: wthidden: calling seq on a lazy seq forces the first element

10:25 wthidden: because it needs to figure out whether there is anything to know if it needs to return nil

10:27 wthidden: Chousuke: Hmmm, that does not bother me so much as I still want to loose the head, and I'm now not sure that will happen in a timely manner.

10:27 AntonyBlakey: rhickey; but in that sense there are no such things as thread errors in software either. The physics of the processor takes care of it. So the lost update isn't a threading error, it's a domain error. And to be honest, I think this is so far off the point that I'm wasting your time on it :/

10:28 Chousuke: AntonyBlakey: maybe you're making it a bit too theoretical :)

10:28 AntonyBlakey: Yes, I have that failing :0

10:30 rhickey: and Clojure's model isn't unique to Clojure. Haskell has MVars and TVars etc

10:30 AntonyBlakey: And not many users relatively speaking.

10:31 I've had no joy doing GUI stuff in Haskell.

10:31 rhickey: I'm just disavowing any claims to novelty

10:43 wthidden: Is there a clojure equivalent of macrolet?

10:45 _ato: wthidden: not yet, it's mentioned here as a possible future feature when compiler is rewritten in Clojure: http://www.assembla.com/wiki/show/clojure/Clojure_Compiler_in_Clojure

10:45 sexpbot: "Clojure Compiler in Clojure | Clojure | Assembla"

10:46 _ato: that's fairly long term future though, I think

10:46 AntonyBlakey: One final thought on the issue of accessibility to developers from more traditional languages, would be syntactic support for swap! and reset!. Like there is for deref. I have no concrete suggestion though.

10:50 wthidden: _ato: thanks. Funny but I was thinking that was the reason, I might have read that bit on wiki and just forgot I read it.

10:56 bsteuber: ,(doc macrolet)

10:56 clojurebot: "([fn-bindings & exprs]); Define local macros that are used in the expansion of exprs. The syntax is the same as for letfn forms."

10:56 bsteuber: ,`macrolet

10:56 clojurebot: clojure.contrib.macro-utils/macrolet

11:06 _ato: oh nice

11:07 wow, macro-utils is one part of contrib I'd completely missed

11:09 bsteuber: not sure it it's realization through eval might be problematic in some cases, though

11:09 *if

11:26 slyphon: Serialization failed, cause: "java.io.NotSerializableException: clojure.lang.ChunkedCons" [90026-126]

11:26 huh?

11:27 chouser: not too surprising. serialization's not fully support on clojure collections, is it?

11:28 slyphon: heh, well, gah

11:28 * slyphon tries to figure out where he failed

11:37 stuartsierra: In general, I think all general-purpose serialization frameworks are doomed to fail.

11:37 chouser: wow. that's sweeping.

11:37 slyphon: come on! XML has totally replaced the need for *all* other serialization formats!

11:37 * slyphon one-ups

11:38 * wthidden thinks XML should be burried deep within a black hole.

11:38 slyphon: yes

11:39 it's the classic "oh! i have a problem, i'll solve it with XML. now I have *two* problems"

11:39 wthidden: lol you'd be lucky to just have "two" problems.

11:39 stuartsierra: By that, I mean that a framework that purports to serialize any arbitrary object, of unknown class, without any programmer intervention or schema definition.

11:39 Is doomed to fail.

11:39 slyphon: or my other favorite: "XML: The answer to a question nobody asked"

11:40 chouser: stuartsierra: oh. heh, yeah, I'd go along with that.

11:40 slyphon: stuartsierra: i dunno, as long as you're not serializing across languages/platforms

11:40 but yeah, it's a thorny issue

11:45 wthidden: Sure its easy, just use OLE...ah no COM, hmm no COM+, no DCOM, no Active X, no .NET 1.0, no .NET 1.1, no .NET 2.0, no .NET 2.1 no .NET 3.0, no .NET 4.0, maybe CORBA?

11:45 slyphon: heh

11:45 chouser: none of those even claim to live up to stuartsierra's requirements.

11:45 slyphon: "you're doing it wrong"

11:46 * chouser lives and breathes protobufs these days.

11:46 slyphon: yeah, my buddy was tellin' me about htat

11:46 bumped into it looking into cassandra

11:46 cassandra made me feel small and dumb, though

11:47 it seemed to shout: YOU'LL NEVER GET A JOB AT GOOGLE!

11:47 chouser: I think people with jobs at google enjoy shouting that.

11:47 slyphon: (not with *those* grades, mister!)

11:47 hahahahaha

11:47 rys: you missed 3.5 and stuff

11:48 vint_cerf: they *gotta* take me now!

12:05 neotyk: LauJensen: thanks for a good post, enjoyed reading as usual :) It reminded me a bit of http://xkcd.com/386/

12:05 sexpbot: "xkcd: Duty Calls"

13:01 Licenser: greetings

13:08 stuartsierra: hi

13:28 ivenkys: afternoon gents

13:33 chessguy: is there a function i can pass something like 'x and get "x" back?

13:34 dakrone: chessguy: (name 'x)

13:34 ,(name 'x)

13:34 clojurebot: "x"

13:34 slyphon: hrm, anyone use ac-mode "autocomplete.el"? i'm trying to figure out how to get it to use the slime-complete-symbol-function

13:34 chessguy: geez, why does it have to be so complicated? :(

13:35 hiredman: name works on anything Named, btw

13:38 slyphon: I would look at ac-sources

13:38 stuartsierra: chessguy: (str 'x) works too

13:41 chessguy: nice

13:42 slyphon: hiredman: yeah, i'm trying to suss it out

13:51 LauJensen: neotyk: Thanks :)

13:55 slyphon: does semantic work with clojure?

13:57 Licenser: and a new library for clojure:D

13:57 slyphon: hah

13:58 Licenser: This is what I like about clojure, you still can write very simple but yet usefull libs

14:06 technomancy: slyphon: I haven't used semantic much, but I don't think it's very necessary when you have slime.

14:06 slyphon: yeah

14:06 i was trying to figure out how to make slime-complete-symbol more useful

14:07 C-c TAB is kind of inconvenient

14:29 LaPingvino: ,(print \H \e \l \l \o \!)

14:29 clojurebot: H e l l o !

15:18 slyphon: how do i access http://snakeyamlrepo.appspot.com/releases/1.6/site/apidocs/org/yaml/snakeyaml/DumperOptions.ScalarStyle.html ?

15:18 sexpbot: "DumperOptions.ScalarStyle (API for SnakeYAML 1.6)"

15:18 * slyphon has a feeling he's about to feel really dumb

15:20 hoeck: slyphon: DumperOptions$ScalarStyle

15:20 slyphon: hrm

15:20 hoeck: $ denotes an inner class

15:20 sexpbot: Command not found. No entiendo lo que est?s diciendo.

15:20 slyphon: sexpbot: thank you

15:21 doh

15:21 "no such namespace"

15:21 * slyphon remembers something about htis from the other day

15:22 slyphon: oh right

15:22 you have to import DumperOptions$ScalarStyle

15:23 hoeck: oh, yes, of course :)

15:23 or use the full package qualified classname

15:23 * slyphon nods

15:23 slyphon: it's not like /

15:23 (the $)

15:25 hoeck: ??

15:25 slyphon: just that DumperOptions$ScalarStyle is a thing unto itself

15:25 hoeck: no, "$" is different and means "inner class"

15:25 slyphon: unlike say DumperOptions/CONST

15:26 right, it's conceptually different from how other dynamic languages treat "inner" stuff and namespaces in general

15:26 hoeck: an inner class is a java class which is defined inside another java class

15:26 slyphon: right

15:26 but that the class name itself *is* A$B

15:27 not B which-happens-to-exist-inside-of A

15:27 hoeck: exactly

15:27 * slyphon makes a note of that

15:28 hoeck: there are even different .class files, one A.class and one A$B.class

15:28 * slyphon nods

15:29 slyphon: to those not steeped in Java, that's a little odd

15:29 or, well, different

15:37 Chousuke: Hm, I wonder if it's possible to create A$B without A actually existing.

15:38 chouser: I think so

15:38 I think it's just a name

15:43 hoeck: Chousuke: "javac Foo$Bar.java" compiles without errors :)

16:00 Raynes: LauJensen: Thank you for the Clojure and Scala similarities post. I couldn't stop laughing when I read that other guys post. Comparing apples to oranges and saying they're the same.

16:01 LauJensen: I wasn't exactly laughing but I know what you mean :)

16:02 Raynes: LauJensen: It was a bit appalling. :\

16:02 LauJensen: hehe

16:02 Its good news in a way - At first they fought us, now they want to be like us, next they'll join us :)

16:02 Raynes: Haha.

16:03 Chousuke: Raynes: but clearly apples and oranges are the same, they're both fruit!

16:03 Raynes: Chousuke: Indeed. But Scala and Clojure are both languages!

16:03 Chousuke: so's english! shoot.

16:03 Licenser: hmm I've a question about lazy seqs, why does this happen:

16:03 (drop 1 (take 3 (map print (range 10)))) ;=> (0123456789nil nil)

16:04 * Chousuke wonders if english is stateful

16:04 Raynes: Because you touch yoursel...

16:04 kotarak: Licenser: chunk

16:04 Licenser: ahh sneaky

16:04 Chousuke: Licenser: map is only partially lazy

16:04 kotarak: ,(drop 1 (take 3 (map print (iterate inc 0)))

16:04 clojurebot: EOF while reading

16:04 Chousuke: Licenser: but size-effect with map are evil anyway

16:05 kotarak: ,(drop 1 (take 3 (map print (iterate inc 0))))

16:05 clojurebot: (nil nil)

16:05 Licenser: Chousuke: I know I don#t need the code it just represented my question most directly :P

16:05 Chousuke: side-effects*... Why am I always dropping the s :(

16:06 LauJensen: Chousuke: because you're *lazy* :)

16:06 Chousuke: I'm not lazy enough to misspell, there must be some other reason ;P

16:07 Licenser: heh

16:07 Raynes: what post did you refear to?

16:07 Chousuke: s and w are pretty close together, maybe my finger slides to w too quickly and not enough pressure is applied on s

16:07 Raynes: Licenser: http://codemonkeyism.com/scala-vsclojure-part-3-similarities/

16:07 sexpbot: "Code Monkeyism: Scala vs.Clojure, part 3 &#8211; the similarities"

16:08 Licenser: thx

16:08 * Raynes looks at "unescape HTML" on his todo list and looks down in shame.

16:08 Licenser: Raynes: i was about to say it but then decided not to put more tasks on your table :P

16:08 Raynes: :p

16:08 Chousuke: Raynes: you were also supposed to make the similarity detector

16:09 Raynes: Chousuke: Indeed, but I got to thinking, and titles are really much prettier than the actual URL.

16:09 Licenser: hmm on the page is a advertisement '12 ACtions to reduce your time to the market' why do I think (reduce actions market time)

16:09 Chousuke: :P

16:10 Licenser: you could also find 12 actions to map your time to the market o.O

16:10 Chousuke: shouldn't that be (let [market (reduce actions time)] ..)

16:11 Licenser: I'm not sure Chousuke

16:11 when I reduce a seq (of tupels) to hash map I do (reduce #(assoc stuff) {} seqthingy)

16:12 livingston: @kotarak, if you only want to print a few of them the print should be on the outside

16:13 Chousuke: Licenser: the result of the reduction is the hashmap you want though

16:13 Licenser: but I don't want the market, I don't even like it very much

16:13 livingston: @kotarak if you instead want part of a string built from the map piece you don't want print you want something else like a concatenat function.,

16:13 Licenser: I'd actually rather reduce the markent :P

16:14 Chousuke: hmm :/

16:14 Licenser: livingston: that was a experiment ;)

16:15 kotarak: I think I'm aware of map, laziness and its pitfalls.

16:15 Licenser: kotarak: I think noone is save from them so P

16:17 dabd: I have one web service which when called for the first time initializes some data structure which is cached. The original Java code used a singleton how can I replicate this in clojure?

16:18 kotarak: dabd: eg. with a delay

16:19 Chousuke: if it really is a global constant for the lifetime of the program, you can just cheat a bit and use alter-var-root!

16:19 hm, did that function have a ! or not.

16:19 ,(doc alter-var-root)

16:19 clojurebot: DENIED

16:19 dabd: I was looking at per-thread-singleton

16:20 livingston: dabd: you just want a var then

16:20 you can bind over it

16:22 dabd: if we already have vars what is the use of per-thread-singleton

16:25 Chousuke: dabd: hm?

16:25 dabd: vars are immutable, but can be thread-locally rebound; And it sounds like that's what you want

16:26 livingston: dbad: I'm hard pressed to tell you... it's more or less doing something like defonce it's just making it easier on a per-thread basis

16:26 dabd: actually I will be calling some Java code that creates the data structures once only

16:27 livingston: then you can use this helper: http://richhickey.github.com/clojure-contrib/singleton-api.html

16:28 dabd: on subsequent requests I would like to to retrieve the single Java instance

16:29 livingston: per-thread-singleton will do that for you, it just creates a closure per thread and sets it to the value of calling your function, if it's already set, you get that

16:31 dabd: per-thread-singleton seems to be what I need since the function that is passed is suposed to return some object (my Java instance) but I was wondering if there was another way to do it with the core clojure library

16:32 livingston: the idiom in global-singleton (at that link) is basically what you do in lisps to get "singletons"

16:33 for per-thread you basically just have to map to the threads to get the right one, in that code they use java's existing ThreadLocal code to do it for you

16:35 dabd: in my case it seems I shouldn't use the global-singleton since it is a web service and there can be concurrent requests, do you agree?

16:36 livingston: I don't know what your "thing" is...

16:36 dabd: It is a web service

16:36 livingston: it depends on what you are tracking/storing in the variable.

16:37 dabd: I will be storing an instance of a Java class

16:38 to be more specific I implemented some web services using a mix of Java + Clojure because I am using a Java framework: Jersey

16:39 I implement the minimal interface Java code (annotation based, that's why it is not full Clojure) and call Clojure from that

16:40 So this Clojure code is living in a web server (GlassFish) that is subject to concurrent requests, that's why I think te per-thread-singleton is more appropriate, but I might be wrong...

16:42 livingston: dabd: sure... nothing so far has been specific enough to say if you need a single thing for your whole app, or one per thread - it really just depends on what it is. (if it's global state for your web app, then you might want just one; if it's a non-thread-safe object that's being manipulated and the requests between threads don't need to be synchronized with each other, then you might want one per thread... etc.)

16:43 stuartsierra: Would it be correct to say that "extend" modifies the Protocol and does not modify the Datatype?

16:43 livingston: dabd: so, that's why I can't really say "just do X"

16:44 Chousuke: stuartsierra: probably, as the whole point if extend is to allow extending things that can't be modified.

16:44 of*

16:45 stuartsierra: That's what I thought.

16:45 in-line methods in deftype/defrecord are added directly to the generated class

16:45 kotarak: stuartsierra: I'd think so. Since it works on classes and interfaces, which cannot be modified, no?

16:46 rfg: Math/round works at the repl but not in a function in a namespace?

16:46 stuartsierra: methods added with 'extend' are attached to the protocol

16:46 dabd: livingsone: thx

16:46 livingston: thx

16:46 Chousuke: stuartsierra: technically you can extend a record type too.

16:47 chouser: extend is always between a protocol and something else, where that something else is a recordtype, datatype, class, interface, etc.

16:47 livingston: dabd: np, I hope it was a little helpful.

16:47 kotarak: chouser: but that something is not modified, no?

16:48 chouser: correct

16:49 Chousuke: I wonder how many datatypes you can extend before it starts to have an adverse effect on performance

16:52 stuartsierra: You can't extend a datatype, really, though, can you?

16:53 That is, you can't modify a datatype after it's been defined.

16:53 chouser: I'm not sure but I think the correct phrasing is extending a protocol to a datatype

16:53 stuartsierra: right

16:53 chouser: except you can do that using the 'extend-type' macro, so maybe i'm wrong

16:54 Chousuke: hmmh

16:54 (doc extend-type)

16:54 clojurebot: Pardon?

16:54 chouser: clojurebot doesn't know anything about 1.2

16:54 Chousuke: too bad

16:57 rfg: seangrove: That texture loading code I showed you was silly in the fact that the allocation of buffers and glGenTextures is happening in a transaction.

16:58 DeusExPikachu: is there a way to change the maven local repository path during runtime, NOT via ~/.m2/settings.conf or <maven install dir>/conf/settings.conf

16:59 lancepantz: any recommendation on jetty 6 vs 7?

17:02 stuartsierra: 'extend-type' is just sugar for 'extend'

17:02 chouser: yes

17:02 stuartsierra: In either case, I think it's the protocol that gets updated

17:02 LaPingvino: hello

17:02 chouser: but the phrasing sounds like extending the type, so maybe that's a valid way to phrase it.

17:02 LaPingvino: little question

17:02 I have a message about maven super-pom in leiningen here

17:03 remleduff: DeusExPikachu: Just about anything (maybe actually anything) in settings.conf can be overridden at the command prompt. I think it should be something like mvn compile -DlocalRepository=yourPath

17:04 DeusExPikachu: remleduff: thanks, but what about if calling it from a java/clojure app?

17:04 remleduff: How are you invoking maven?

17:04 DeusExPikachu: remleduff: haven't wrote the code yet, but something like the way leiningen does (I'm actually planning on modifying it)

17:05 LaPingvino: can anyone see what's wrong here? http://gist.github.com/374394

17:05 Borkdude: LaPingvino: how was the Amsterdam Clojurians meetup, on a side note?

17:06 LaPingvino: was great

17:06 10 participants

17:06 never so big :P

17:07 Borkdude: LaPingvino: maybe the { is unmatched?

17:07 o no sorry

17:08 remleduff: DeusExPikachu: I think that means you'd use the maven embedder: http://maven.apache.org/guides/mini/guide-embedding-m2.html if you look at the example, the configuration variable has a setLocalRepository method

17:08 sexpbot: "Maven - The Maven Embedder"

17:09 DeusExPikachu: remleduff: on that page, I can't find the "setLocalRepository" method

17:09 Borkdude: What do you guys do on such an evening?

17:11 DeusExPikachu: remleduff: although, I'd assume it exists, thanks for the pointers

17:12 remleduff: DeusExPikachu: Yeah, I saw that method by googling "maven Configuration embedder" and looking at the source, didn't find a really good link though, looks like the source code will be your friend ;)

17:12 DeusExPikachu: remleduff: what is the name of that jar?

17:12 remleduff: Just a note: lein currently uses the maven ant task, it doesn't use the embedder api to my knowledge

17:14 Ermm, it's "org.apache.maven/maven-embedder"

17:15 http://www.jarvana.com/jarvana/browse/org/apache/maven/maven-embedder/

17:15 sexpbot: "/org/apache/maven/maven-embedder/ - Maven Repository Browser - Jarvana"

17:16 DeusExPikachu: remleduff: heh, k thanks, also, looking at the lib/ directory of leiningen, it does not contain that jar, which agrees with what you said earlier

17:23 Borkdude: LaPingvino: change the clojure dep to: [org.clojure/clojure "1.1.0"]

17:23 that works in my setup

17:28 LaPingvino: tnx :)

17:29 is it normal that it downloads something labeled alpha-SNAPSHOT ???

17:30 Borkdude: dunno...

17:34 _ato: LaPingvino: looks like lein-gae is the one pulling the alpha-SNAPSHOT in

17:36 [lein-gae "1.0.0-SNAPSHOT" :exclusions [org.clojure/clojure org.clojure/clojure.contrib]] and adding contrib 1.1.0 to your deps might do the trick if it's causing problems

17:40 Borkdude: _ato, how can you see it actually is going to use a different jar?

17:45 _ato: I just guessed by looking at the poms for the dependencies. Some sort dependency tree printing (like mvn dependency:tree) for debugging this would be a nice addition to lein, not sure how hard the maven API would make implementing it though

17:45 livingston: what's the best way to test for a non-empty seq-able thing e.g. the equivalent of consp in lisp except in clojure I'd like it to work for both lists and vectors

17:45 Borkdude: LaPingvino: I just read the Amsterdam Clojurians update, are you considering to go to Brussels?

17:45 LaPingvino: just maybe

17:46 depends on all of the holiday altogether

17:49 _ato: ,livingston: possibly (and (coll? x) (seq x))

17:49 clojurebot: Invalid token: livingston:

17:49 Borkdude: lein help appengine-setup

17:49 nil

17:49

17:50 _ato: livingston: if you want to match even more seqable things (like Strings), not just collections there's a seqable? in clojure.contrib.core

17:51 livingston: _ato thanks - I don't see coll? on my cheat sheet,... wouldn't have thought of that

17:53 _ato: I don't think I need all seqable things, but definitely lists and vectors and getting both of those simply was driving me a bit nuts

17:57 Borkdude: _ato: don't you mean (and (coll? x) (seq? x))

17:57 with a question mark behind seq

17:58 livingston: no because that will return true for '() and '[]

17:58 I want those to be in the false category

17:59 _ato: Borkdude: nope. the (seq ...) is basically equivalent to (not (empty ...))

17:59 Borkdude: ah I see

17:59 _ato: at least when using this as a test

17:59 livingston: so a function that will return true for a non-empty list or vector and everything else including an empty list or vector should be false (including just symbols etc.)

18:00 _ato: seq it has benefit (other than conciseness) over (not (empty ...)) that you actually return the seq rather than true, which might be more useful in some cases

18:00 Borkdude: ic

18:00 ok, gotta go, good night all

18:01 _ato: and I did mean empty? there, not empty ;-)

18:01 slyphon: gah

18:02 * slyphon hates on the classpath

18:04 slyphon: doh, is there some reason why lein would copy a jar file into the lib/ directory, but not include it in the classpath?

18:05 * slyphon frowns

18:06 slyphon: oh, restart-inferior-lisp hits you for 100 points of damage

18:07 Intensity: Hi. I'm wondering the best way is to check whether a parameter passed into a function is (1) a number or (2) a hash.

18:09 dnolen: ,(type 1)

18:09 clojurebot: java.lang.Integer

18:09 dnolen: ,(type {})

18:09 clojurebot: clojure.lang.PersistentArrayMap

18:09 livingston: i have a lot going on in my repl right now, but if I have something in (ns foo.bar.baz) anything that is in (ns foo.bar) is automatically visible, right?

18:09 technomancy: ,(number? 1)

18:09 clojurebot: true

18:10 Intensity: Ok, I had been able to use (type input) in my Linux REPL, but for some reason the version of Clojure running in Aquamacs isn't recognising type. Is this added in 1.1?

18:10 _ato: livingston: I don't think so, namespaces don't inherit

18:10 technomancy: livingston: namespaces are only hierarchical on disk, not in any other way

18:11 livingston: oh, well, I wonder how I got this to happen then...

18:11 hircus: Intensity: best way to try a recent enough Clojure is to install ELPA from within Emacs/Aquamacs and then install swank-clojure

18:13 dnolen: Intensity: or Netbeans+Enclojure, Eclipse+CounterClockwise and drop in jars you've built from master. Pretty simple.

18:14 Intensity: Ok. I had manually reassigned my inferior-lisp-program, following some other instructions. I'd prefer to get the ELPA setup working. I'll follow those instructions again.

18:16 zakwilson: I'm having a problem where I produced a file with (spit "foo" (str a-map)) and trying to read it with (read-string (slurp "foo")) fails with java.lang.Exception: Invalid token: :

18:17 On a 50mb file. Smaller files produced the same way work.

18:19 hircus: zakwilson: sounds like something to file a bug in Assembla -- it does not matter what the content of the map is, as long as it's over 50mb?

18:20 rhickey: new datatypes doc in progress: http://clojure.org/datatypes

18:20 zakwilson: hircus: I haven't done much testing, but it seems that it doesn't.

18:20 rhickey: and protocols: http://clojure.org/protocols

18:23 livingston: i think I fell off the planet

18:24 I asked if I just needed to use the dependent ns and I would be fine - then my client disconnected

18:29 _ato: rhickey: I really like the way you've listed the "opinions" on the datatypes page. I think saying explicitly helps a lot in showing why they are how they are and the way you should be thinking when using them. It means you're less likely to naiively assume that say the lack of inheritance is just a missing feature, not an intentional design decision.

18:40 remleduff: rhickey: In the datatypes bullet list, you kind of gloss over that deftype allows mutable fields. May want to say something like, "for performance reasons though it is strongly discouraged... etc"? Are you interested in a typo check as well? I saw a couple of incidental problems.

18:56 dabd: is calling PersistenHashMap from Clojure the best way to create a map from a Java HashMap?

18:59 _ato: dabd: http://en.wikibooks.org/wiki/Clojure_Programming/FAQ#How_can_I_convert_a_Java_HashMap_to_a_Clojure_map.3F

18:59 sexpbot: "Clojure Programming/FAQ - Wikibooks, collection of open-content textbooks"

19:01 dabd: _ato: thx

19:10 robink: Hello

19:22 joshua-choi: I've got a question: when should I use defonce? Any guidelines?

19:32 technomancy: I use it for top-level stateful java objects

19:33 joshua-choi: technomancy: Would it be unnecessary for top-level Clojure refs?

19:34 technomancy: joshua-choi: it'd be necessary if you're reloading a lot in development and want to keep state

19:34 but it shouldn't be necessary outside development

19:34 joshua-choi: I see

19:35 * technomancy is a bit weird and doesn't actually use refs

19:42 kzar: What's the easiest way to download a webpage from Clojure if you need to send POST data and other things?

19:44 xeqi: kzar: curl -d ?

19:47 kzar: nm, thought you meant from a clojure server

20:11 _ato: kzar: maybe http://github.com/technomancy/clojure-http-client

20:22 kzar: _ato: thanks

21:08 dabd: how can I convert a PersistentHashMap to a HashMap?

21:09 slyphon: (zipmap (keys phm) (vals phm))

21:10 dabd: that creates a clojure map I need a java.util.HashMap

21:14 tomoj: has anyone figured out a sensible way to deal with developing with incanter.processing?

21:14 don't want to have to keep restarting the jvm to clear out zombie animations

21:14 slyphon: hah

21:15 * slyphon imagines tomoj working on "Night Of The Living Dead: Java Edition"

21:15 tomoj: hehe

21:16 _ato: ,(java.util.HashMap. {:a 1 :b 2})

21:16 clojurebot: #<HashMap {:b=2, :a=1}>

21:16 _ato: dabd: ^

21:22 cemerick: dabd: note that PHM *are* java.util.Maps

21:23 ,(instance? java.util.Map (hash-map))

21:23 clojurebot: true

21:23 cemerick: ...so hopefully the API you're working with is sane, and accepts Map, rather than specializing on a concrete impl. :-)

21:24 dabd: ok thx

21:58 slyphon: if i have two refs, and i want to make sure both of them are set when reading, do i need to deref inside of a dosync?

21:59 * slyphon starts thinking this should probably be a single ref

21:59 hiredman: ensure

22:00 slyphon: hrm

22:00 mm'kay

22:02 isn't there still a race there?

22:02 to read the second ref?

22:03 hrm, actually, i'm setting both at the same time

22:03 hiredman: nope

22:05 slyphon: wow, XA is confusing

22:06 or, at least Atomikos is

22:12 gah!

22:12 no support for clojure in exuberant ctags

22:12 boo!

Logging service provided by n01se.net