#clojure logs

2010-04-21

00:00BorkdudeHow do I put a type annotation on a function, just for the sake of example?
00:01BorkdudeI mean, for the return type
00:06_atoBorkdude: (defn #^String foo [] ...)
00:08Borkdude_ato, txn
00:08Borkdudetnx I mean
00:16Borkdude_ato and in a let?
00:18_ato(let [#^String foo (blah)] ...) I think
00:18_atoyou can probably type-hint either the variable or the expression actually and it'll propagate it
00:20Borkdude_ato, I tried this: (let [#^String n 3] n)
00:20Borkdudebut it doesn't complain about 3 being a non-string value
00:20_atotype hints never complain
00:21_atothey're just hints to allow the compiler to optimize the common path
00:21_atoit's still dynamically typed, it doesn't do type checking
00:22BorkdudeI see
00:23_atoif you want to check whether its working, turn on *warn-on-reflection*
00:23Borkdudehow do I do that from the repl?
00:27_ato(set! *warn-on-reflection* true)
00:27joshua-choiBorkdude: (set! *warn-on-reflection* true) or (binding [*warn-on-reflection* true] ...)
00:27joshua-choiDang
00:27_ato:)
00:28cheezeyer. does clojure not have a push function or similar for a stack? o_O
00:30hiredmanconj
00:31cheezeyya i just found that loL
00:31cheezeywhy wouldn't it be called push? :\
00:31joshua-choicheezey: Because it doesn't always push. conj adds to the from for lists and seqs, but in the back for vectors.
00:32somniumbecause its hard to make push into a clever pun on cons
00:32hiredmanwhat would push do differently than conj??
00:32joshua-chois/front/front
00:32joshua-choiAugh
00:32joshua-chois/from/front
00:32_atoand 'push' usually tends to imply a mutable datastructure
00:32cheezeyoh that's weird.
00:32cheezeywell so does pop but that's in there
00:33joshua-choi,(doc pop)
00:33clojurebot"([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."
00:33_atohmm, guess so
00:33joshua-choiRight. Never mind then. :P
00:33joshua-choiconj is short for "conjoin".
00:33joshua-choiRich Hickey just decided to name it that. :)
00:34cheezey>_> im sure this has messed up more than just me
00:34Borkdude_ato, I was thinking set-something, but then I thought, a root binding of a var can't be changed
00:34joshua-choicheezey: On what? What conj is called?
00:34Borkdudeso what kind of thing is *warn-on-reflection* if it's not a var?
00:34joshua-choiBorkdude: It is a var.
00:34cheezeyjoshua-choi: yeah :x
00:35Borkdudejoshua-choi: so how come I can change it's binding?
00:35cheezeyi guess i asked you guys a bit early since i found it like 30 seconds after asking but stilllll
00:35_atoBorkdude: *warn-on-reflection* is a thread-locally bound var
00:35_atowhich can be set
00:35_ato(but it only affects the current thread)
00:35joshua-choicheezey: I believe it's because that's what the previous Lisps, Common Lisp and Scheme, called it. I think.
00:35joshua-choiBorkdude: Vars are actually mutable.
00:35joshua-choiVery rarely
00:35joshua-choiAnd for very specific reasons
00:36Borkdudejoshua, mutable on thread-level you mean?
00:36joshua-choiVars whose names are surrounded by *'s are "allowed" to be mutated by the user.
00:36joshua-choiYeah.
00:36joshua-choiIt's still thread-safe
00:36joshua-choiBut it can get annoying
00:36joshua-choiWhich is why it's rare, as it should be
00:36joshua-choiThere are certain useful things that it makes possible
00:37Borkdudeis 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?
00:37joshua-choiI believe so.
00:37joshua-choiUnless you call something that initiates another thread.
00:38joshua-choipmap, for instance.
00:38Borkdudejoshua-choi, function calls initiate threads I thought
00:39joshua-choiMmm, I don't think so; not unless that function calls something that does create another thread.
00:39joshua-choiOf course, that's the current state.
00:39joshua-choiJVM and CPU improvements in the future may eventually make all functions use their own thread
00:39Borkdudeah, 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?
00:39joshua-choiBut right now, there's little point in doing that
00:40joshua-choiGood question. This is something that I still don't get completely, because I have never needed to think about it
00:40joshua-choiI can tell you that the binding does *not* create a new thread. Just a new scope.
00:40joshua-choiI don't know what happens if you create a new thread inside a binding form.
00:40hiredmanwarn-on-reflection is compile time
00:41joshua-choiYes, that's also a good point
00:41hiredmanbindings are thread local
00:41_atoif you create a new thread inside a binding the new thread will see the root value
00:41hiredmancompilation happens on the repl thread (the place where eval is called)
00:41joshua-choihiredman: Okay, I figured as much.
00:41_atoit won't see the new value
00:41joshua-choiOops. I mean @_ato.
00:43BorkdudeI 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...
00:44joshua-choiBorkdude: Ask again here sometime anytime
00:44Borkdudejoshua-choi: tnx
00:46joshua-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.
01:26cheezeyif 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
01:27Chousukethat's the way, but use :else instead of true
01:27Chousukeit's more idiomatic
01:28cheezeyChousuke: thanks, what exactly does :... do?
01:28Chousuke:foo things are just keywords
01:28Chousukeevaluate to themselves
01:29Chousuke,:foo
01:29clojurebot:foo
01:30Chousukethe trick is that in a boolean context keywords (as anything not false or nil) have a true value
01:31Chousukeyou could use :otherwise or :boring if you wanted but :else is the convention :P
01:32cheezeyya
01:32_atojoshua-choi: I think it's because threads can't tell who their parent is, so they can't inherit (at least efficiently anyway)
01:33joshua-choiI see
01:33_atothat's what I've always assumed anyway, I could well be wrong ;-)
01:36cheezeythis is probably the wrong way of thinking about functional programming, but i want to call two functions... how would that be done
01:36joshua-choiOn a single object?
01:36cheezeynope
01:37cheezeylol i am bad at fp. D=
01:37Chousukecall two functions in which way? :/
01:37joshua-choiElaborate a litte...do you mean just (a) (b)?
01:37cheezeyyeah
01:37Chousukeyou can just call them.
01:37joshua-choiYou can just do that in most cases.
01:37joshua-choiAlways when you're not within a form.
01:37cheezeywell it's part of (cond ...)
01:37clojurebotCL conditions is http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html
01:37joshua-choiAh.
01:37Chousukethen use (do ..)
01:38Chousukethough generally calling more than one function in a cond means you have side-effects :)
01:40cheezeywhich is bad in fp right =\
01:40joshua-choiIt depends, but they should be isolated.
01:40ChousukeThat 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
01:40Chousukeeg. do you have printing out the results mixed with calculating the results?
01:41cheezeyim still wrapping my head around the whole thing so i guess this is gonna be a slow and painful transition
01:41joshua-choiDo you understand what a side-effect is?
01:41cheezeychanging of state?
01:42Chousukein general, any action which changes behaviour depending on factors outside the function
01:42joshua-choiChanging of state is one example
01:42joshua-choiOther examples: printing messages, writing to a file, connecting to the Internet
02:53LauJensenHey Crew
02:54zmilayes, sir
04:11Licenser_morning
04:24tomojdoes a deftype sound good for a triple of doubles that you're going to iterate over?
04:25tomoji.e. (iterate f the-3d-coord)
04:25tomojthey get fast method dispatch, but it'll box and unbox, right?
04:27tomojoh, they can be primitive, huh
04:27hoecktomoj: yes
04:28tomojwhat's the type hint for primitives look like?
04:28tomoj#^double ?
04:28hoeck(deftype Point [#^int x, #^int y])
04:28tomojcool, thanks
04:29hoeckjust like normal typehints
04:29Licenser_hmm it seems that c.c does not depend on clojure itself in the jar o.O that leads to odd things
04:29Licenser_I talk about the maven artifacts
04:30Licenser_which leads to a situation where the dependency resolver of maven
04:30Licenser_ / lein
04:30Licenser_gives you clojure-1.2 and c.c-1.1
04:32tomojI depend on both
04:32tomojyou're getting c.c-1.2 AND c.c-1.1?
04:33Licenser_tomoj: nono I juist get c.c-1.1 but c-1.2
04:33Licenser_but c.c-1.1 should depend onc c-1.1 in my oppinion
04:33tomojyou don't depend on c-1.1 explicitly?
04:33tomojI always have both
04:33Licenser_no
04:34Licenser_http://github.com/Licenser/clj-sandbox/blob/master/project.clj
04:34Licenser_that is what I do
04:35tomojhuh, what does that do?
04:35tomojoh, defer to the dependency resolver?
04:36tomojnow I see what you mean
04:36Licenser_it tells maven that I want clojure <= 1.2 and >= 1.1
04:40_atohttp://build.clojure.org/releases/org/clojure/clojure-contrib/1.1.0/clojure-contrib-1.1.0.pom
04:40_atoseems to specify it there
04:41_atoI'm not sure how maven picks the versions when you give it a range
04:44Licenser__ato: you'
04:44Licenser_re right iot does
04:44Licenser_I didn't expect maven to be odd here :P (oddly enough)
04:47bsteuberLicenser_: Without any conflicts, Maven dependency resolution should be fairly straighforward
04:48bsteuberbut with conflicts, it uses some sort of "nearest wins" policy
04:52Licenser_bsteuber: but [1.1,1.2] and "1.1.0" should not be a conflict
04:52Licenser_it should resolve to 1.1.0
04:52Licenser_and then it should clojure itself to be forced 'down' to 1.1.0 too
04:52Licenser_or it should at least whine 'i can't have this'
04:53bsteubermaybe some other dependency requires clojure 1.2?
04:54bsteuberor you can check it it whines with -X
05:03cYmensattvik: Do you have a couple of minutes to help me install the hg version of vimclojure?
05:18LauJensenFor 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/
05:18sexpbot"Clojure &amp; Scala Similarities???Twins separated at?birth? | BEST IN CLASS"
05:27esjLauJensen: I've got as far as "This is exciting, so lets have a look!" and am already in fear...
05:27LauJensenFear of what?
05:28esja very polite evisceration
05:28LauJensenNot at all
05:29esji'm still reading...
05:30LauJensenBut 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
05:31esjI ilke the post it cuts to the relevent points
05:32LauJensenGlad to hear it
05:35bendlashi, folks
05:36esjyo
05:57sattvikcYmen: Sure, I'll help as much as I can.
05:59cYmenSo, first things first. Apparently there is a nailgun server in the repo in src/main/java/com/martiansoftware/nailgun
06:00cYmenI'm not sure how to set my classpath so I can run it..
06:01cYmensattvik: Did you compile your own nailgun server instead?
06:02sattvikcYmen: If you build vimclojure, it is automatically included in vimclojure.jar, I believe.
06:03cYmensattvik: OK. I have a big issue with building, too.
06:04cYmenThe readme talks about adding things to my build dependencies but I'm not sure what it's talking about.
06:04carkhi'm trying to set paredit up with clojure mode, but it won't automate the curly-braces {}
06:04cYmenIt doesn't seem to make sense to add anything editor specific to a project so I don't know what to do.
06:04carkhany idea ?
06:04cYmenAnd it doesn't come with a build.xml for ant anymore.
06:05sattvikcYmen: Hmmm... let me look into that.
06:06sattvikcYmen: Yes, you'll need gradle to build VimClojure now.
06:07_atocarkh: make sure your using paredit version 22 (beta) http://mumble.net/~campbell/emacs/paredit-beta.el
06:07carkhahh thanks
06:09sattvikcYmen: Just checked the latest readme. It seems like he's discouraging building VimClojure from source, and instead importing it in via your build tool.
06:09carkh_ato: it's working, thanks
06:10raek_ato: thanks! I've been looking for that too
06:10cYmensattvik: And how would I import that? That clojars url doesn't seem to exist.
06:12sattvikcYmen: You can try version "2.2.0-SNAPSHOT", though I don't know which one is considered to be an official release.
06:13raekhrm, this didn't solve the curly braces problem for me...
06:15cYmensattvik: Where did you find that?
06:15sattvikcYmen: 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.
06:16sattvikcYmen: I just searched clojars for 'vimclojre'.
06:20LauJensenClojure is #12 on Hacker News :) ... and #26
06:22sattvikcYmen: 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.
06:22LauJensensattvik: The guy who wrote VimClojure is also the one who wrote Clojuresque, the Gradle plugin
06:22LauJensenI imagine you hit 'gradle build' and thats it :) Otherwise, check for tasks in build.gradle
06:24cYmenhmhm clojuresque hm..gradle hm...damn I've never used any of this!
06:25sattvikLauJensen: 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.
06:26LauJensenHardly anybody uses Clojure compared to C++, but thats not really an argument which says anything about quality
06:26LauJensenBesides, he's been good enough to put up at least 3 blog posts showing the ropes of Clojuresque, and its not exactly rocket science :)
06:26raekyay! got curlies to work in paredit
06:27raekanyone else had to add this to yout .emacs? http://gist.github.com/373669
06:28carkhi just followed ato's advice and downloaded betta paredit, works wonder in clojure-mode it seems
06:28raekI had the beta paredit and the latest clojure-mode...
06:28carkhstrange =/
06:28raekanyway, it works for me now, so I'm happy
06:29LauJensenraek: Thanks for sharing!
06:29LauJensenUuuh, #3 on Hacker News now :)
06:29sattvikLauJensen: 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.
06:30cYmenas usual there are a million tools for the job
06:30cYmenand hopefully at some point a handful of clever people will get together and build $THE_STANDARD
06:30LauJensensattvik: 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 ...
06:33cYmenWill I need cojuresque to build vimclojure with gradle?
06:34LauJensenI suspect its added as a dependencies to the build file itself, so probably not
06:34LauJensenIf you build Clojureql, it will first fetch clojuresque and load it, then fetch CQLs dependencies and build
06:34LauJensen(clever)
06:35cYmenI'm confused. But gradle build just says that the plugin with the id clojure is not available.
06:35sattvikLauJensen: 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.
06:35cYmenI'll read the gradle tutorial. *sigh*
06:36LauJensencYmen: check out Meikels blog - I'm sure he's commented on it somewhere
06:36LauJensen(sure = I imagine so)
06:36cYmen:)
06:36LauJensensattvik: Fairly unknown??? :) I think you'll be hard pressed to back that up with facts
06:38cemerickThere are no facts when it comes to language and tool debates. Only innuendo and relative volume.
06:38sattvikcYmen: Try http://gist.github.com/373685
06:38LauJensenAnyway - 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
06:38LauJensencemerick: and emotion, dont forget :)
06:39sattvikcYmen: 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.
06:39cemerickright, so we have innuendo, relative volume, emotion, and ego. For sure, technical details will work themselves out somewhere...
06:40LauJensenhehe, feeling a little sarcastic this morning Chas? :)
06:41sattvikLauJensen: 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.
06:41cemerickYeah, it's hard to say that gradle is a common tool outside the groovy world. *shrug*
06:41LauJensenOk
06:41cemerickLauJensen: 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.
06:42vegaiI wonder if this is a faq...
06:42LauJensencemerick: Im sorry to hear that. But on a positive note I've rectified some of the misconceptions about scala=clojure
06:42cemerickSomeone older than I will likely pop up now and say, "Uh, so what else is new?"
06:42vegaiwhat do I do wrong if my helloworld built with lein jar tells me
06:42vegaivegai@mab:~/src/test$ java -jar hellotest.jar
06:42vegaiException in thread "main" java.lang.NoClassDefFoundError: hellotest
06:43ChousukeI think equating scala with clojure in any way is somewhat of a mistake. they're completely different languages :/
06:44vegaiit seems to me that java, scala and clojure are quite nicely analogous to C, C++ and common lisp
06:44ChousukeI mean, no-one's equating Clojure with haskell
06:44LauJensenChousuke: which is weird, as they have more in common that clojure/scala
06:45ChousukeLauJensen: yes.
06:45vegaiwell, scala does have more haskelly typing, doesn't it?
06:45LauJensenBut I think most Scala users actually perceive that Scala is a lot more like Haskell than Clojure is
06:45vegaiuhm, sorry. Logical mistake on my part.
06:45eevar2clojure is closer to scheme, tho? (I only know cl)
06:45LauJensenI wouldn't say so, no
06:46LauJensen(chousuke would)
06:46Chousukeyes :P
06:46Chousukebut in the end, any such comparisons are only good for a quick approximation
06:47cemerickChousuke: it's that caveat that no one seems to have considered, never mind internalized.
06:47cYmensattvik: Is that an ant buildfile?
06:48Chousukecemerick: unfortunately :/
06:48sattvikcYmen: Yes.
06:49cYmensattvik: The error messages start with [javac] /Users/simon/code/clojure/vimclojure/src/main/java/vimclojure/Nail.java:30: package clojure.lang does not exist
06:49cYmenI haven't worked with ant so...
06:52sattvikcYmen: 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.
06:53cYmensattvik: I'll try to figure out gradle and if it doesn't work in about an hour I'll try your script again.
06:53cYmenNeed to focus on something for now.
06:53sattvikcYmen: no problem.
06:59cYmenWow..building the hello world example with gradle takes 2.4 seconds
07:22lessthantristanis their some better way of doing: (apply -> (cons {:a {:b {:c 1}}} '(:a :b :c))) (which doesn't work)
07:24lessthantristanof course, the desired result is: (-> {:a {:b {:c 1}}} :a :b :c)
07:24raeklessthantristan: can you give an (possibly mock-) example of what data you have and what data you want
07:24raekah, ok
07:24raekyou cant apply -> since it's a macro
07:25raekso that's why it doesn't work
07:25raekmaybe you could use get-in
07:25raek,(get-in {:a {:b {:c 1}}} [:a :b :c])
07:25clojurebot1
07:26lessthantristanyes! that's exactly what i was looking for
07:26lessthantristanthanks raek :)
07:28raekthere's also assoc-in update-in and dissoc-in (the last one is in clojure.contrib.core, though)
07:36raeklessthantristan: also, apply can take additional args before the argument list
07:36raek(apply f 1 2 [3 4 5]) can be seen as (apply f [1 2 3 4 5])
07:37raek,(doc apply)
07:37clojurebot"([f args* argseq]); Applies fn f to the argument list formed by prepending args to argseq."
07:51LauJensennetsplit, or just me?
07:52noidi[14:51] >>> Signoff LauJensen: #clojure (Remote host closed the connection)
07:54LauJensenkthx
08:07cemerickLauJensen: nice post (the separated at birth one)
08:08LauJensencemerick: Thanks a lot
08:08cemerickI don't really agree with the OO point though.
08:08cemerick(a remarkably minor difference, of course)
08:09LauJensenYou don't agree that Clojure is not Object Oriented?
08:10cemerickIt'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. :-)
08:11LauJensenI disagree, I think its not not not OO, but it interops with an OO language
08:12cemerickQuestion then: is javascript OO?
08:13LauJensenI would say so
08:13cemerickOK, that's interesting. I thought you might have been falling into the trap of thinking that only Java/C# OO qualifies. :-)
08:15LauJensenNo - 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
08:15rhickeycemerick: 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?
08:16rhickeyOf 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
08:17fogusrhickey: What would you call it otherwise?
08:17rhickeyCLOS showed OO wasn't about having the polymorphic methods inside the classes
08:18rhickeyfogus: abstraction-oriented?
08:18cemerickI won't bother trying to talk intelligently about haskell. :-)
08:18fogusoooooo. I like that
08:18cemerickHowever, insofar as you can associate methods with types (protocols and records), I'd say clojure is a flavor of OO.
08:19rhickeycemerick: Haskell type classes do similar things
08:19cemerickOr, it provides for a flavor of OO.
08:19cemerickIt's entirely possible that between Java, C#, javascript, smalltalk, and perhaps clojure and haskell, the term has lost all real meaning.
08:20foguscemerick: I think that's more likely
08:20rhickeycemerick: 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
08:20cemerickrhickey: so a Java class with all final fields isn't OO?
08:21rhickeycemerick: no
08:21cemerickHeh, that's ballsy. :-)
08:21rhickeyit's not any more OO than a Haskell type, a C struct etc
08:21LauJensenI was expecting some dancing around the answer, not just a 'no' :)
08:21_atoI 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".
08:21fogusrhickey: Is there a precedent for abstraction-oriented programming? Or is it a confluence of different ideas?
08:21_ato"oriented" is a fuzzy word
08:22rhickeyfogus: good OO is abstraction oriented
08:22cemerickIsn't "abstraction oriented" an even worse term? C is abstraction oriented too. :-/
08:22rhickeyHaskell with type classes is abstraction oriented
08:22rhickeycemerick: what language constructs in C embody abstractions?
08:23rhickeyi.e. let you name and circumscribe them?
08:24bsteuberpreprocessor macros lol
08:24cemerickrhickey: for loops are an abstraction over jumps.
08:25cemerickI'm just saying, "abstraction" isn't exactly less overloaded than "object".
08:25rhickeyinterestingly, prototype-based OO is not particularly abstraction oriented
08:25_atobut loops are an abstraction defined for you, you (as the programmer) aren't the one defining them
08:25rhickeycemerick: right, all terms are overloaded, yet still meaningful and useful
08:25fogusrhickey: Not being terribly familiar with Haskell type classes I'm not sure how/if Clojure's model differs
08:26rhickeybut clearly, Smalltalk/C++/Java style OO combines abstractions in the forms of classes/interfaces with mutable objects. The mutable objects aren't the abstractions
08:27rhickeyfogus: 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
08:30rhickeyThe 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?
08:30cemerickI'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.
08:31rhickeycemerick: it certainly doesn't, insofar as you have no identity without adding a reference around it
08:32cemerickIt's amazing how much one can get done in this field without having a thorough grasp of core concepts.
08:32rhickeycemerick: 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
08:34rhickeyI 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
08:35LauJensenrhickey: The 'are we there yet' left me with the impression that it would be impossible
08:35rhickey(rebuilding objects by making every field a reference doesn't count)
08:35rhickeyLauJensen: that talk ended with this as an open question
08:35LauJensenI remember
08:36rhickeyx.foo(y. z) ==> (alter x foo y z ?)
08:36Licenser_rhickey: I think thgat will be hard, most people associate objects with mutability/changing state
08:38rhickeyLicenser_: but Clojure offers a recipe that does just that. It just adds the ability to say @object and get a value
08:39rhickeyClojure says, objects have values
08:39LauJensenrhickey: If thats all, why isnt building objects with every field a reference good enough ?
08:39Licenser_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
08:39rhickeyLauJensen: because the resulting object can't present itself as a value
08:40rhickeyor rather, I contend (via Clojure)
08:41Licenser_hmm well how about a ref that holds a map
08:41rhickeyLicenser_: yes, that's what we do in Clojure instead of objects
08:41Licenser_then changing the object would be just derefferencing it, altering it and fine
08:41LauJensenOk I see - So all function application on the object should be in sync with all of its fields , like the entire thing was transactional
08:42Licenser_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
08:42sattvikrhickey: 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.
08:43rhickeyThat'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
08:43cemerickrhickey: 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.
08:43Licenser_well we could make a simple way to do stuff like (alter x (@x function) params)
08:43LauJensenAh yes, I get it now
08:44_atorhickey: 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?
08:44rhickeycemerick: really? how could you model the simplest OO-like collection for a Java programmer given only an immutable instance?
08:45cemerickrhickey: have "mutating" methods return new values. Lots of Java-only APIs do this as a matter of course.
08:45rhickey_ato: It goes to what cemerick and I are discussing - is a record instance an object, or a reference + record instance?
08:45cemerickrhickey: that obviously doesn't address anything you'd like to solve w.r.t. identity, but it "feels" just fine to a Java dev.
08:46rhickeycemerick: you've been working in some alternate universe of functional Java, where no one uses java.util collections?
08:46cemerick(as long as you can convince them of the efficiency of it all, though that's less and less a problem.)
08:47cemerickrhickey: not alternate, but many, many shops and projects are adopting immutable libraries such as google collections.
08:48cemerickand others are producing APIs that avoid mutability as well
08:49rhickeyso 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
08:50rhickeycemerick: without some MT-safe place to put/access the return values, immutable APIs/objects are insufficient
08:51sattvikcemerick: 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.
08:51fogusrhickey: It seems fundamentally at odds to "do state properly" while maintaining something that a j.u.c Java programmer would recognize.
08:52fogus... feel comfortable with that is
08:52cemerickrhickey: That's a tougher hill to climb. STM is far, far harder sell than immutability to a Java mindset.
08:53rhickeyfogus: 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
08:53LauJensenWhen 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 :)
08:53cemericksattvik: Not the norm now, but I think it's likely it will be the norm sooner rather than later.
08:54rhickeycemerick: one could have transactional objects, or atomic objects, or async objects, per reference type used
08:54rhickeycemerick: all could be made to feel like x.mutate(y)
08:54cemerickIn EE-land in particular, where people just throw stuff at a MQ or such to solve parallelization and concurrency issues, etc.
08:55cemerickrhickey: 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".
08:56rhickeycemerick: right, to the extend frameworks create single-threaded apartments, people never need leave their mutable object approach, unles they find values valuable otherwise
08:56cemerickPut another way, I'd say it's a decidedly minority viewpoint that immutable "objects" aren't Objects. ;-)
08:56sattvikcemerick: 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.
08:57rhickeycemerick: I think until we establish that objects are identity+value we are hopeless. Immutable values are not objects
08:57fogusrhickey: 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?
08:57LauJensenrhickey: 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 ?
08:57rhickeyif they are, then you;ll just have to invent another term for identity + "object"
08:58cemerickrhickey: 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.
08:58rhickeyfogus: ref->record still always provides access to the full record as a value at any time, so no
08:59_atoWhat 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
08:59rhickeycemerick: 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.
09:00sattvikrhickey: Just out of curiousity, why do you say that STM is a barrier for Java people?
09:00rhickey_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.
09:00rhickeysattvik: I didn't say that
09:01fogusrhickey: 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
09:01cemerickrhickey: 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.
09:01rhickeyfogus: there would be a new capability - get the value of an object - that is missing in today's OO
09:02sattvikrhickey: Sorry, I misread the message.
09:02sattvikcemerick: Just out of curiousity, why do you say that STM is a barrier for Java people?
09:02fogusrhickey: I think I follow now
09:03rhickeycemerick: 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.
09:04fogusrhickey: And is that "get the value of an object" the place where Kafka comes into play?
09:04cemerickrhickey: 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.
09:04rhickeycemerick: e.g. "I was maintaing a set of logged-in users, accessed throughout my app"
09:04rhickeycemerick: that's just not true. The old object held the result, the new method leaves them wondering where to put it
09:05rhickeymutable object method becomes value + function + place to put the result
09:06cemerickrhickey: 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.
09:06_atojust making everything immutable means you're just working with values, ie a pure computation, it misses the identity half of the picture
09:06rhickeythe entire point of Clojure was that it came with stuff for that last bit
09:07rhickeycemerick: but those APIs just beg the where to put it question
09:08cemerickrhickey: Back on the MQ, or in the clustered session state, or whatever.
09:08rhickeycemerick: and maybe people will just adopt value + reference as Clojure delivers
09:09rhickeycemerick: If they do, it will constitute a move to value- and abstraction-oriented programming, IMO, and a rejection of objects
09:09rhickeywhich suits Clojure just fine
09:09cemerickexactly
09:09sattvikcemerick: 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.
09:11cemericksattvik: I wasn't suggesting that servlet sessions become values themselves -- that's a stateful service, just like writing to disk.
09:11rhickeyfogus: sorry, I missed your Kafka question, please restate
09:12cemerickrhickey: Would you find this "transactional object" concept useful in general, above and beyond what values and reference types get us now?
09:15rhickeycemerick: 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
09:15rhickeycemerick: OTOH, if t helps people conform to their mental model, the combo could have great appeal, essentially ensuring correct use of the constructs
09:16AWizzArdRegarding the mental model and OOP: i missed inheritance in the discussion so far.
09:16rhickeyone problem is how the type of reference impacts the use of the object. Will that become a property of whatever replaces 'new'?
09:17cemerickrhickey: 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.
09:18rhickeycemerick: problem to solve - making Clojure less alien to non-functional programmers without simply supplying them their same old broken stuff
09:19cemerickrhickey: you may find people coming to you faster and easier than you thought possible. *shrug*
09:19rhickeycemerick: as is?
09:19cemerickyes, as is.
09:20cemerickAs long as you don't say "Clojure isn't object oriented" too loudly. ;-)
09:20rhickeycemerick: that's already the case :)
09:20cemerickheh
09:20Chousukeheh
09:20ChousukeI suppose it's better to say what clojure is, instead of what it isn't :P
09:21cemerickrhickey: well, you can say "with defrecord, clojure is now OO!!!11!!"
09:21AWizzArdcemerick: wouldn't that require inheritance?
09:21rhickeycemerick: 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
09:21cemerickAWizzArd: I'm speaking from a positioning / marketing standpoint here more than technical.
09:21AWizzArdbefore they had defrecord + protocols they had defstruct + defgeneric
09:22rhickey(defrecord Foo [a b])
09:22rhickey(def f (Foo. 1 2))
09:22rhickey(how-do-I-make-fs-b=? 42)
09:22cemerickrhickey: honestly, the two make for objects, outside this channel anyway. :-)
09:23rhickeycemerick: I don't think so ^^
09:23rhickeyI guarantee that will be a common question
09:24cemerickrhickey: OK, but then you need to tell people that Strings aren't objects, at which point they'll think you're nuts.
09:24AWizzArdis 15 an object?
09:24rhickeycemerick: the 'there are non-mutable classes in Java' argument is secondary. People have mutable objects and want replacements
09:25rhickeycemerick: I don't think you can say, it's like Java OO where every class is like String
09:25rhickeypeople wouldn't use Java if every class was like String
09:25rhickeyit's insufficient
09:26esjbe like a mathematician and define 'immutable object' and 'immutable object oriented' to your liking and proceed
09:26AWizzArdIs 15 a value and x in (def x 15) an object?
09:27cemerickAWizzArd: If I put my Java hat on and forget what I've learned from rhickey, then when boxed, 15 is an object.
09:27AWizzArdhmm
09:28rhickeyOO 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
09:28cemerickrhickey: 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.
09:29rhickeycemerick: and everyone is using actors for identity? Or just secreting away values in vars and hoping for the best? Or using locks?
09:29cemerickrhickey: 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.
09:30cemerickrhickey: combination of options A, B, and using MQs and such, probably.
09:30rhickeycemerick: the transactional bit isn't important, just reference (ref/atom/agent etc) + value
09:30cemericksure, either way
09:31rhickeycemerick: MQ's et al have huge problems in requiring object serialization
09:31cemerickAbsolutely.
09:31rhickeyvs say, atoms :)
09:31cemerickBut it's an easy, dumb way to parallelize operations.
09:32rhickeycemerick: we're not talking about parallelization, but identity. The set of logged in users
09:32cemerickAnd I'd say you'll have no problem getting people to use an atom properly with a record.
09:33rhickeycemerick: looking forward to your help with that :)
09:33cemerickrhickey: I do my best. You should have seen this PHP friend of mine take to clojure like duck to water. It was crazy.
09:33rhickeycemerick: wow
09:34cemerickI don't think immutability is the biggest hurdle by a long shot.
09:34rhickeycemerick: what is, IYO?
09:35cemerickRealizing, and then, accepting that programming doesn't need to be so bloody complicated.
09:35rhickeyis that a hard sell? :)
09:35cemerickYes. You'd be surprised.
09:37cemerickPeople 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.
09:39AntonyBlakeyjust to people wanting to write lots of code?
09:39Licenser_rhickey: with the bugs :P
09:40AntonyBlakeyWhat about the inherent mutability and (pragmatic) acceptance of identity in our everyday experience of the world.
09:41Licenser_hmm is there a ideomatic way to execute some code every n seconds?
09:41Licenser_AntonyBlakey: my world is static
09:42AntonyBlakeyLicenser_: you just need to tune in.
09:42cemerickAntonyBlakey: I think the resistance to immutability is rapidly waning.
09:42Licenser_AntonyBlakey: I work in a Siemens branch - we are static :P
09:42sattvikOn 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.
09:42AntonyBlakeycemerick: That is certainly the case, but that isn't the same as saying that mutability isn't required
09:44cemerickAntonyBlakey: And the little corners of mutability that are necessary are well-covered by the reference types.
09:44AntonyBlakeyI'd contend that the desire for, and use of mutability is related to our physical experiences in a Kantian sense
09:45AntonyBlakeySo for many problems, the immutable solution requires an additional set of cognitive tools that can act as the ground terms.
09:45AntonyBlakeyi.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.
09:45rhickeycemerick: 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
09:48cemerickrhickey: back to the simplicity aspect. Consider the classic: compare what ants needs to the typical Java impl, and people are stunned.
09:48AntonyBlakeyOne 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.
09:51AntonyBlakeyRather 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.
09:51rhickeyAntonyBlakey: Clojure is that experiment
09:51AntonyBlakeyi.e. Refs are like boxes/containers. What is like a piece of paper?
09:52rhickeyAntonyBlakey: a vector in a reference
09:53AntonyBlakeyNo, thats like putting a piece of write-once paper in a box.
09:53ChousukeAntonyBlakey: a written-to paper is not the same as an empty paper
09:53AntonyBlakeyIt misses the essential nature of the physical experience
09:54AntonyBlakeyBut the paper doesn't change. It has identity.
09:54Chousukeyou can't take the paper out of the box, write to it, and put it back without taking it out of the box
09:54Chousukebut you can look at it and do things based on what's on it
09:54AntonyBlakeyNot the point. I don't have my paper in a box in the real world.
09:54cemerickAntonyBlakey: I think someone hasn't seen rhickey's key preso :-) http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey
09:54sexpbot" InfoQ: Are We There Yet?"
09:54ChousukeAntonyBlakey: well, an envelope then
09:54ChousukeAntonyBlakey: a translucent envelope
09:55AntonyBlakeyStill not right. An accounting ledger gets modified directly. That's the physical relationship people have with the thing.
09:55Chousukeyes, but the old "values" of the accounting ledger haven't gone anywhere
09:56Chousukethey're in your memory
09:56Chousukeas you once saw them
09:56Chousukeand you work based on that memory.
09:56AntonyBlakeyNo, you hand the piece of paper to your colleague
09:56AntonyBlakeyHe writes on it.
09:57Chousukeyes, because he has a lock on it
09:57Chousuke:P
09:57Chousuke(he's holding it, preventing anyone else from writing to it)
09:57mefestoisn't the piece of paper acting as a ref at the point?
09:57AntonyBlakeycemerick: saw it when it came out, I'll rewatch it.
09:57mefestoit's a ref with a value that is written on it
09:57Chousukemefesto: I suppose.
09:57cemerickAntonyBlakey: The issues you're raising are pretty well hashed out there.
09:58AntonyBlakeyThe 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.
09:58AntonyBlakeycemerick: yes, it's coming back to me as I run it.
09:58Chousukea piece of paper is not mutable.
09:58mefestoAntonyBlakey: all you really care about is the value on that paper at any point in time
09:59AntonyBlakeyIf you cut the piece of paper then it's certainly mutated.
09:59rhickeyhttp://en.wikipedia.org/wiki/Schrödinger's_cat
09:59AntonyBlakeyBut in any case, 99% of people will say that you write on the piece of paper and change it.
09:59Chousukehm, I think I'm a bit confused now.
10:00Chousukeso I suppose it's better indeed to think that the paper is the ref
10:00AntonyBlakeyMy point is the relationship between our fundamental cognitive models as generated my out physical embodiment, and the abstractions we see in the language.
10:00Chousukebecause it's the thing that's "mutating"
10:00mefestoAntonyBlakey: 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:01AntonyBlakeyYou 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:01ChousukeAntonyBlakey: 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:01mefestothen 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:01ChousukeAntonyBlakey: you could never work with a paper that could just *poof* change what's written on it
10:02AntonyBlakeyYou're talking about a granularity that isn't used in the 'real' world.
10:02ChousukeAntonyBlakey: and even just following what someone is writing onto a paper is very difficult
10:03ChousukeI wonder if we are agreeing or what.
10:05chouserAntonyBlakey: I think the natural conclusion to the argument you're making is very similar to existing object-oriented models.
10:05ChousukeAntonyBlakey: if you're writing to a paper it's basically the equivalent of executing a function to change the value on the paper
10:05ChousukeAntonyBlakey: and when you're done, the function ends and the paper has a new, complete value.
10:06chouserthat 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:06Chousukethen someone can take a look at it, remember its contents, and do something
10:06AntonyBlakeycemerick: 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:06AntonyBlakeythe end-point abstractions understandable (intuitive) has been lost.
10:07rhickeyAntonyBlakey: 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:08chouserAntonyBlakey: 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:08AntonyBlakeychouser: 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:08rhickeywhat we see when we look at paper is a snapshot produced by light reflected from it at a point in time.
10:08cemerickAntonyBlakey: Virtually nothing we do in software has anything to do with how we "intuitively experience" the world.
10:08AntonyBlakeyPersonally I like Rich's choices.
10:09AntonyBlakeyrhickey: that's a reductionist viewpoint. It may be correct, but it's not how people think.
10:09chouserWell, 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:10AntonyBlakeyIn the same way that saying "I've having a seretonin induced sense of connection' is *not* the same as "I love you"
10:10ChousukeAntonyBlakey: 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:10AntonyBlakeyWe dom'
10:11AntonyBlakeyWe don't experience them as discrete values.
10:11chouserSo 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:11AntonyBlakeyThis is the point about it being fundamentally Kantian argument about embodiment.
10:11Chousukebecause the brain forms a "continuous" series from them.
10:11rhickeyAntonyBlakey: 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:13chouserman, if we could retry street-crossing, we could get a lot more of it done with a lot fewer stoplight-locks.
10:14rhickeyall 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:15rhickeyperception and memory must become part of the model, and references + values make that easy and efficient
10:15AntonyBlakeyI'm not advocating OO, although we may have wandered through that. I'm advocating a model that is congitively based
10:16ChousukeDo you have an idea what such a model would look like?
10:17AntonyBlakeyTo 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:17AntonyBlakeyChousuke: no
10:17AntonyBlakeyI'm just trusting in Rich.
10:19AntonyBlakeyBut one point I'd make is that the physical world at our level of granularity isn
10:19AntonyBlakey'
10:20AntonyBlakey.. isn't thread safe
10:21rhickeyAntonyBlakey: can two people write on exactly the same part of the paper at the same time?
10:21AntonyBlakeySo 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:22vegaidoes clojure have formal models really?
10:22AntonyBlakeyNo, 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:22ChousukeI never saw clojure's model as "formal". But it does have a model, unlike most languages
10:22AntonyBlakeyvegai: well it's not exactly Z, but it's a principle approach
10:22rhickeyClojure's model is not formal, it is purely intuitional
10:22Chousukethe problem is exactly that most languages don't even have a model for this.
10:23AntonyBlakeyI think Clojure is more amenable to reasoning than, say, Java's memory model.
10:23rhickeyAntonyBlakey: but two cars can't occupy the same space at the same time either. Physics is dealing with the threads in some sense
10:24wthiddenQuestion? Does a (seq of a lazy-seq) retain its laziness?
10:24Chousukewthidden: calling seq on a lazy seq forces the first element
10:25Chousukewthidden: because it needs to figure out whether there is anything to know if it needs to return nil
10:27wthiddenChousuke: 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:27AntonyBlakeyrhickey; 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:28ChousukeAntonyBlakey: maybe you're making it a bit too theoretical :)
10:28AntonyBlakeyYes, I have that failing :0
10:30rhickeyand Clojure's model isn't unique to Clojure. Haskell has MVars and TVars etc
10:30AntonyBlakeyAnd not many users relatively speaking.
10:31AntonyBlakeyI've had no joy doing GUI stuff in Haskell.
10:31rhickeyI'm just disavowing any claims to novelty
10:43wthiddenIs there a clojure equivalent of macrolet?
10:45_atowthidden: 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:45sexpbot"Clojure Compiler in Clojure | Clojure | Assembla"
10:46_atothat's fairly long term future though, I think
10:46AntonyBlakeyOne 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:50wthidden_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:56bsteuber,(doc macrolet)
10:56clojurebot"([fn-bindings & exprs]); Define local macros that are used in the expansion of exprs. The syntax is the same as for letfn forms."
10:56bsteuber,`macrolet
10:56clojurebotclojure.contrib.macro-utils/macrolet
11:06_atooh nice
11:07_atowow, macro-utils is one part of contrib I'd completely missed
11:09bsteubernot sure it it's realization through eval might be problematic in some cases, though
11:09bsteuber*if
11:26slyphonSerialization failed, cause: "java.io.NotSerializableException: clojure.lang.ChunkedCons" [90026-126]
11:26slyphonhuh?
11:27chousernot too surprising. serialization's not fully support on clojure collections, is it?
11:28slyphonheh, well, gah
11:37stuartsierraIn general, I think all general-purpose serialization frameworks are doomed to fail.
11:37chouserwow. that's sweeping.
11:37slyphoncome on! XML has totally replaced the need for *all* other serialization formats!
11:38slyphonyes
11:39slyphonit's the classic "oh! i have a problem, i'll solve it with XML. now I have *two* problems"
11:39wthiddenlol you'd be lucky to just have "two" problems.
11:39stuartsierraBy that, I mean that a framework that purports to serialize any arbitrary object, of unknown class, without any programmer intervention or schema definition.
11:39stuartsierraIs doomed to fail.
11:39slyphonor my other favorite: "XML: The answer to a question nobody asked"
11:40chouserstuartsierra: oh. heh, yeah, I'd go along with that.
11:40slyphonstuartsierra: i dunno, as long as you're not serializing across languages/platforms
11:40slyphonbut yeah, it's a thorny issue
11:45wthiddenSure 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:45slyphonheh
11:45chousernone of those even claim to live up to stuartsierra's requirements.
11:45slyphon"you're doing it wrong"
11:46slyphonyeah, my buddy was tellin' me about htat
11:46slyphonbumped into it looking into cassandra
11:46slyphoncassandra made me feel small and dumb, though
11:47slyphonit seemed to shout: YOU'LL NEVER GET A JOB AT GOOGLE!
11:47chouserI think people with jobs at google enjoy shouting that.
11:47slyphon(not with *those* grades, mister!)
11:47slyphonhahahahaha
11:47rysyou missed 3.5 and stuff
11:48vint_cerfthey *gotta* take me now!
12:05neotykLauJensen: thanks for a good post, enjoyed reading as usual :) It reminded me a bit of http://xkcd.com/386/
12:05sexpbot"xkcd: Duty Calls"
13:01Licensergreetings
13:08stuartsierrahi
13:28ivenkysafternoon gents
13:33chessguyis there a function i can pass something like 'x and get "x" back?
13:34dakronechessguy: (name 'x)
13:34dakrone,(name 'x)
13:34clojurebot"x"
13:34slyphonhrm, anyone use ac-mode "autocomplete.el"? i'm trying to figure out how to get it to use the slime-complete-symbol-function
13:34chessguygeez, why does it have to be so complicated? :(
13:35hiredmanname works on anything Named, btw
13:38hiredmanslyphon: I would look at ac-sources
13:38stuartsierrachessguy: (str 'x) works too
13:41chessguynice
13:42slyphonhiredman: yeah, i'm trying to suss it out
13:51LauJensenneotyk: Thanks :)
13:55slyphondoes semantic work with clojure?
13:57Licenserand a new library for clojure:D
13:57slyphonhah
13:58LicenserThis is what I like about clojure, you still can write very simple but yet usefull libs
14:06technomancyslyphon: I haven't used semantic much, but I don't think it's very necessary when you have slime.
14:06slyphonyeah
14:06slyphoni was trying to figure out how to make slime-complete-symbol more useful
14:07slyphonC-c TAB is kind of inconvenient
14:29LaPingvino,(print \H \e \l \l \o \!)
14:29clojurebotH e l l o !
15:18slyphonhow do i access http://snakeyamlrepo.appspot.com/releases/1.6/site/apidocs/org/yaml/snakeyaml/DumperOptions.ScalarStyle.html ?
15:18sexpbot"DumperOptions.ScalarStyle (API for SnakeYAML 1.6)"
15:20hoeckslyphon: DumperOptions$ScalarStyle
15:20slyphonhrm
15:20hoeck$ denotes an inner class
15:20sexpbotCommand not found. No entiendo lo que est?s diciendo.
15:20slyphonsexpbot: thank you
15:21slyphondoh
15:21slyphon"no such namespace"
15:22slyphonoh right
15:22slyphonyou have to import DumperOptions$ScalarStyle
15:23hoeckoh, yes, of course :)
15:23hoeckor use the full package qualified classname
15:23slyphonit's not like /
15:23slyphon(the $)
15:25hoeck??
15:25slyphonjust that DumperOptions$ScalarStyle is a thing unto itself
15:25hoeckno, "$" is different and means "inner class"
15:25slyphonunlike say DumperOptions/CONST
15:26slyphonright, it's conceptually different from how other dynamic languages treat "inner" stuff and namespaces in general
15:26hoeckan inner class is a java class which is defined inside another java class
15:26slyphonright
15:26slyphonbut that the class name itself *is* A$B
15:27slyphonnot B which-happens-to-exist-inside-of A
15:27hoeckexactly
15:28hoeckthere are even different .class files, one A.class and one A$B.class
15:29slyphonto those not steeped in Java, that's a little odd
15:29slyphonor, well, different
15:37ChousukeHm, I wonder if it's possible to create A$B without A actually existing.
15:38chouserI think so
15:38chouserI think it's just a name
15:43hoeckChousuke: "javac Foo$Bar.java" compiles without errors :)
16:00RaynesLauJensen: 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:01LauJensenI wasn't exactly laughing but I know what you mean :)
16:02RaynesLauJensen: It was a bit appalling. :\
16:02LauJensenhehe
16:02LauJensenIts good news in a way - At first they fought us, now they want to be like us, next they'll join us :)
16:02RaynesHaha.
16:03ChousukeRaynes: but clearly apples and oranges are the same, they're both fruit!
16:03RaynesChousuke: Indeed. But Scala and Clojure are both languages!
16:03Chousukeso's english! shoot.
16:03Licenserhmm I've a question about lazy seqs, why does this happen:
16:03Licenser(drop 1 (take 3 (map print (range 10)))) ;=> (0123456789nil nil)
16:04RaynesBecause you touch yoursel...
16:04kotarakLicenser: chunk
16:04Licenserahh sneaky
16:04ChousukeLicenser: map is only partially lazy
16:04kotarak,(drop 1 (take 3 (map print (iterate inc 0)))
16:04clojurebotEOF while reading
16:04ChousukeLicenser: but size-effect with map are evil anyway
16:05kotarak,(drop 1 (take 3 (map print (iterate inc 0))))
16:05clojurebot(nil nil)
16:05LicenserChousuke: I know I don#t need the code it just represented my question most directly :P
16:05Chousukeside-effects*... Why am I always dropping the s :(
16:06LauJensenChousuke: because you're *lazy* :)
16:06ChousukeI'm not lazy enough to misspell, there must be some other reason ;P
16:07Licenserheh
16:07LicenserRaynes: what post did you refear to?
16:07Chousukes and w are pretty close together, maybe my finger slides to w too quickly and not enough pressure is applied on s
16:07RaynesLicenser: http://codemonkeyism.com/scala-vsclojure-part-3-similarities/
16:07sexpbot"Code Monkeyism: Scala vs.Clojure, part 3 &#8211; the similarities"
16:08Licenserthx
16:08LicenserRaynes: i was about to say it but then decided not to put more tasks on your table :P
16:08Raynes:p
16:08ChousukeRaynes: you were also supposed to make the similarity detector
16:09RaynesChousuke: Indeed, but I got to thinking, and titles are really much prettier than the actual URL.
16:09Licenserhmm on the page is a advertisement '12 ACtions to reduce your time to the market' why do I think (reduce actions market time)
16:09Chousuke:P
16:10Licenseryou could also find 12 actions to map your time to the market o.O
16:10Chousukeshouldn't that be (let [market (reduce actions time)] ..)
16:11LicenserI'm not sure Chousuke
16:11Licenserwhen I reduce a seq (of tupels) to hash map I do (reduce #(assoc stuff) {} seqthingy)
16:12livingston@kotarak, if you only want to print a few of them the print should be on the outside
16:13ChousukeLicenser: the result of the reduction is the hashmap you want though
16:13Licenserbut I don't want the market, I don't even like it very much
16:13livingston@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:13LicenserI'd actually rather reduce the markent :P
16:14Chousukehmm :/
16:14Licenserlivingston: that was a experiment ;)
16:15kotarakI think I'm aware of map, laziness and its pitfalls.
16:15Licenserkotarak: I think noone is save from them so P
16:17dabdI 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:18kotarakdabd: eg. with a delay
16:19Chousukeif it really is a global constant for the lifetime of the program, you can just cheat a bit and use alter-var-root!
16:19Chousukehm, did that function have a ! or not.
16:19Chousuke,(doc alter-var-root)
16:19clojurebotDENIED
16:19dabdI was looking at per-thread-singleton
16:20livingstondabd: you just want a var then
16:20livingstonyou can bind over it
16:22dabdif we already have vars what is the use of per-thread-singleton
16:25Chousukedabd: hm?
16:25Chousukedabd: vars are immutable, but can be thread-locally rebound; And it sounds like that's what you want
16:26livingstondbad: 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:26dabdactually I will be calling some Java code that creates the data structures once only
16:27livingstonthen you can use this helper: http://richhickey.github.com/clojure-contrib/singleton-api.html
16:28dabdon subsequent requests I would like to to retrieve the single Java instance
16:29livingstonper-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:31dabdper-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:32livingstonthe idiom in global-singleton (at that link) is basically what you do in lisps to get "singletons"
16:33livingstonfor 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:35dabdin 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:36livingstonI don't know what your "thing" is...
16:36dabdIt is a web service
16:36livingstonit depends on what you are tracking/storing in the variable.
16:37dabdI will be storing an instance of a Java class
16:38dabdto be more specific I implemented some web services using a mix of Java + Clojure because I am using a Java framework: Jersey
16:39dabdI implement the minimal interface Java code (annotation based, that's why it is not full Clojure) and call Clojure from that
16:40dabdSo 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:42livingstondabd: 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:43stuartsierraWould it be correct to say that "extend" modifies the Protocol and does not modify the Datatype?
16:43livingstondabd: so, that's why I can't really say "just do X"
16:44Chousukestuartsierra: probably, as the whole point if extend is to allow extending things that can't be modified.
16:44Chousukeof*
16:45stuartsierraThat's what I thought.
16:45stuartsierrain-line methods in deftype/defrecord are added directly to the generated class
16:45kotarakstuartsierra: I'd think so. Since it works on classes and interfaces, which cannot be modified, no?
16:46rfgMath/round works at the repl but not in a function in a namespace?
16:46stuartsierramethods added with 'extend' are attached to the protocol
16:46dabdlivingsone: thx
16:46dabdlivingston: thx
16:46Chousukestuartsierra: technically you can extend a record type too.
16:47chouserextend is always between a protocol and something else, where that something else is a recordtype, datatype, class, interface, etc.
16:47livingstondabd: np, I hope it was a little helpful.
16:47kotarakchouser: but that something is not modified, no?
16:48chousercorrect
16:49ChousukeI wonder how many datatypes you can extend before it starts to have an adverse effect on performance
16:52stuartsierraYou can't extend a datatype, really, though, can you?
16:53stuartsierraThat is, you can't modify a datatype after it's been defined.
16:53chouserI'm not sure but I think the correct phrasing is extending a protocol to a datatype
16:53stuartsierraright
16:53chouserexcept you can do that using the 'extend-type' macro, so maybe i'm wrong
16:54Chousukehmmh
16:54Chousuke(doc extend-type)
16:54clojurebotPardon?
16:54chouserclojurebot doesn't know anything about 1.2
16:54Chousuketoo bad
16:57rfgseangrove: 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:58DeusExPikachuis 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:59lancepantzany recommendation on jetty 6 vs 7?
17:02stuartsierra'extend-type' is just sugar for 'extend'
17:02chouseryes
17:02stuartsierraIn either case, I think it's the protocol that gets updated
17:02LaPingvinohello
17:02chouserbut the phrasing sounds like extending the type, so maybe that's a valid way to phrase it.
17:02LaPingvinolittle question
17:02LaPingvinoI have a message about maven super-pom in leiningen here
17:03remleduffDeusExPikachu: 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:04DeusExPikachuremleduff: thanks, but what about if calling it from a java/clojure app?
17:04remleduffHow are you invoking maven?
17:04DeusExPikachuremleduff: haven't wrote the code yet, but something like the way leiningen does (I'm actually planning on modifying it)
17:05LaPingvinocan anyone see what's wrong here? http://gist.github.com/374394
17:05BorkdudeLaPingvino: how was the Amsterdam Clojurians meetup, on a side note?
17:06LaPingvinowas great
17:06LaPingvino10 participants
17:06LaPingvinonever so big :P
17:07BorkdudeLaPingvino: maybe the { is unmatched?
17:07Borkdudeo no sorry
17:08remleduffDeusExPikachu: 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:08sexpbot"Maven - The Maven Embedder"
17:09DeusExPikachuremleduff: on that page, I can't find the "setLocalRepository" method
17:09BorkdudeWhat do you guys do on such an evening?
17:11DeusExPikachuremleduff: although, I'd assume it exists, thanks for the pointers
17:12remleduffDeusExPikachu: 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:12DeusExPikachuremleduff: what is the name of that jar?
17:12remleduffJust a note: lein currently uses the maven ant task, it doesn't use the embedder api to my knowledge
17:14remleduffErmm, it's "org.apache.maven/maven-embedder"
17:15remleduffhttp://www.jarvana.com/jarvana/browse/org/apache/maven/maven-embedder/
17:15sexpbot"/org/apache/maven/maven-embedder/ - Maven Repository Browser - Jarvana"
17:16DeusExPikachuremleduff: 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:23BorkdudeLaPingvino: change the clojure dep to: [org.clojure/clojure "1.1.0"]
17:23Borkdudethat works in my setup
17:28LaPingvinotnx :)
17:29LaPingvinois it normal that it downloads something labeled alpha-SNAPSHOT ???
17:30Borkdudedunno...
17:34_atoLaPingvino: looks like lein-gae is the one pulling the alpha-SNAPSHOT in
17:36_ato[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:40Borkdude_ato, how can you see it actually is going to use a different jar?
17:45_atoI 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:45livingstonwhat'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:45BorkdudeLaPingvino: I just read the Amsterdam Clojurians update, are you considering to go to Brussels?
17:45LaPingvinojust maybe
17:46LaPingvinodepends on all of the holiday altogether
17:49_ato,livingston: possibly (and (coll? x) (seq x))
17:49clojurebotInvalid token: livingston:
17:49Borkdudelein help appengine-setup
17:49Borkdudenil
17:49Borkdude
17:50_atolivingston: if you want to match even more seqable things (like Strings), not just collections there's a seqable? in clojure.contrib.core
17:51livingston_ato thanks - I don't see coll? on my cheat sheet,... wouldn't have thought of that
17:53livingston_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:57Borkdude _ato: don't you mean (and (coll? x) (seq? x))
17:57Borkdudewith a question mark behind seq
17:58livingstonno because that will return true for '() and '[]
17:58livingstonI want those to be in the false category
17:59_atoBorkdude: nope. the (seq ...) is basically equivalent to (not (empty ...))
17:59Borkdudeah I see
17:59_atoat least when using this as a test
17:59livingstonso 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_atoseq 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:00Borkdudeic
18:00Borkdudeok, gotta go, good night all
18:01_atoand I did mean empty? there, not empty ;-)
18:01slyphongah
18:04slyphondoh, is there some reason why lein would copy a jar file into the lib/ directory, but not include it in the classpath?
18:06slyphonoh, restart-inferior-lisp hits you for 100 points of damage
18:07IntensityHi. 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:09dnolen,(type 1)
18:09clojurebotjava.lang.Integer
18:09dnolen,(type {})
18:09clojurebotclojure.lang.PersistentArrayMap
18:09livingstoni 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:09technomancy,(number? 1)
18:09clojurebottrue
18:10IntensityOk, 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_atolivingston: I don't think so, namespaces don't inherit
18:10technomancylivingston: namespaces are only hierarchical on disk, not in any other way
18:11livingstonoh, well, I wonder how I got this to happen then...
18:11hircusIntensity: best way to try a recent enough Clojure is to install ELPA from within Emacs/Aquamacs and then install swank-clojure
18:13dnolenIntensity: or Netbeans+Enclojure, Eclipse+CounterClockwise and drop in jars you've built from master. Pretty simple.
18:14IntensityOk. 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:16zakwilsonI'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:17zakwilsonOn a 50mb file. Smaller files produced the same way work.
18:19hircuszakwilson: 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:20rhickeynew datatypes doc in progress: http://clojure.org/datatypes
18:20zakwilsonhircus: I haven't done much testing, but it seems that it doesn't.
18:20rhickeyand protocols: http://clojure.org/protocols
18:23livingstoni think I fell off the planet
18:24livingstonI asked if I just needed to use the dependent ns and I would be fine - then my client disconnected
18:29_atorhickey: 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:40remleduffrhickey: 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:56dabdis calling PersistenHashMap from Clojure the best way to create a map from a Java HashMap?
18:59_atodabd: http://en.wikibooks.org/wiki/Clojure_Programming/FAQ#How_can_I_convert_a_Java_HashMap_to_a_Clojure_map.3F
18:59sexpbot"Clojure Programming/FAQ - Wikibooks, collection of open-content textbooks"
19:01dabd_ato: thx
19:10robinkHello
19:22joshua-choiI've got a question: when should I use defonce? Any guidelines?
19:32technomancyI use it for top-level stateful java objects
19:33joshua-choitechnomancy: Would it be unnecessary for top-level Clojure refs?
19:34technomancyjoshua-choi: it'd be necessary if you're reloading a lot in development and want to keep state
19:34technomancybut it shouldn't be necessary outside development
19:34joshua-choiI see
19:42kzarWhat's the easiest way to download a webpage from Clojure if you need to send POST data and other things?
19:44xeqikzar: curl -d ?
19:47xeqikzar: nm, thought you meant from a clojure server
20:11_atokzar: maybe http://github.com/technomancy/clojure-http-client
20:22kzar_ato: thanks
21:08dabdhow can I convert a PersistentHashMap to a HashMap?
21:09slyphon(zipmap (keys phm) (vals phm))
21:10dabdthat creates a clojure map I need a java.util.HashMap
21:14tomojhas anyone figured out a sensible way to deal with developing with incanter.processing?
21:14tomojdon't want to have to keep restarting the jvm to clear out zombie animations
21:14slyphonhah
21:15tomojhehe
21:16_ato,(java.util.HashMap. {:a 1 :b 2})
21:16clojurebot#<HashMap {:b=2, :a=1}>
21:16_atodabd: ^
21:22cemerickdabd: note that PHM *are* java.util.Maps
21:23cemerick,(instance? java.util.Map (hash-map))
21:23clojurebottrue
21:23cemerick...so hopefully the API you're working with is sane, and accepts Map, rather than specializing on a concrete impl. :-)
21:24dabdok thx
21:58slyphonif 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:59hiredmanensure
22:00slyphonhrm
22:00slyphonmm'kay
22:02slyphonisn't there still a race there?
22:02slyphonto read the second ref?
22:03slyphonhrm, actually, i'm setting both at the same time
22:03hiredmannope
22:05slyphonwow, XA is confusing
22:06slyphonor, at least Atomikos is
22:12slyphongah!
22:12slyphonno support for clojure in exuberant ctags
22:12slyphonboo!