#clojure log - Jun 26 2008

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

3:34 Lau_of_DK: Morning gents, straight to business: I need to make a JComboBox. and init it with some values. They need to be passed as a cstor argument in the form of Object(), how do I make that Object from Clojure?

3:46 cgrand: (to-array [arg1 arg2 argN])

3:58 Lau_of_DK: thanks cgrand

4:03 cgrand: yw

4:05 arbscht: cgrand: hi, I'm curious: how did you locate my blog post with the mini snake implementation? :)

4:06 Lau_of_DK: mini snake? gimme link =)=

4:07 arbscht: Lau_of_DK: it's not that interesting http://www.plt1.com/1070/even-smaller-snake/

4:07 cgrand: arbscht: google alert on clojure

4:08 arbscht: cgrand: ah

4:09 Lau_of_DK: impressively small

4:11 Im having some syntax trouble. I did (def globs (ref hash-map)) for my globals, now when I want to commit a value, how do I get about it? I start firing casting errors with something like (alter globs (assoc :mykey "myval)) or in a transaction I get an invocattiontargetexception

4:13 cgrand: arbscht: submitted to reddit http://www.reddit.com/info/6p1ku/comments/

4:13 Btw you could flatten "collision?" by removing two of the three "and"

4:15 lau_of_dk: no need for that many parens :-) just use (alter globs assoc :mykey "myval) in a transaction

4:16 arbscht: cgrand: hm yes, thanks

4:17 Lau_of_DK: clever man... but cgrand that fires an "hash_map cannot be cast to Associative"

4:19 cgrand: what does hash-map contains?

4:19 Lau_of_DK: nothing yet, but its supposed to contain all my global-vars

4:19 so that I reference all the globs to it, and extract the values

4:20 cgrand: I mean: an instance of java.util.HashMap or a clojure map?

4:21 Lau_of_DK: (def globs (ref hash-map))

4:21 I suppose/hope that its a clojure-map

4:22 cgrand: eureka: what you wanted to write is (def globs (ref {})) or (def globs (ref (hash-map)))

4:25 lau_of_dk: does it work now?

4:25 Lau_of_DK: hang on

4:26 ahem

4:26 explain it to the slow student please

4:26 why does (hash-map) make the difference?

4:27 cgrand: (ref hash-map) creates a reference to the function hash-map

4:27 Lau_of_DK: Its a bit fuzzy to me, why does (alter bla bla assoc) work? I would image that (assoc) belong in () to evaluate it

4:27 cgrand: (ref (hash-map)) creates a ref to the result of evaluating (hash-map), ie the empty hashmap

4:32 Lau_of_DK: I understand that, but in relation to what you said about (alter ... asoc) compared to (alter ... (assoc..)) its not wholly clear to me

4:34 cgrand: alter, commute and send are functions not macros. So when you put parens around (assoc :mykey "myval") what is inside must be valid so as to be evaluated prior to the function (eg alert) call; here the map upon which you operate is missing so the content of (assoc :mykey "myval") must be break into pieces and passed directly to alter which will pu them all together with the current value of the ref

4:35 break -> broken

4:40 More succintly: to write (alter globs (assoc :mykey "myval)) alter has to be macro since (assoc :mykey "myval) is inomplete.

4:42 inomplete -> incomplete

4:51 Lau_of_DK: ok cgrand, very good explanation, thanks alot

8:55 Hey blackdog

8:55 blackdog: hi

9:28 rhickey: cgrand: *agent* type hint in place

9:30 cemerick: added *file*, but does not use URL path, because same path is put in debug info, where jar stuff breaks debuggers

9:33 cgrand: rhickey: thanks!

9:37 rhickey: have you seen the bug reported by wwmorgan yesterday? (sorted-set) returns an empty hashmap

9:38 cemerick: rhickey: Thanks :-) Too bad about *file* not always being absolute, though.

9:38 blackdog: cemerick, what is *file*

9:38 rhickey: cemerick: begs the question of what is absolute when it's in a jar

9:39 cgrand: just looking now

9:39 cemerick: blackdog: path to the clj file being loaded (via load-file, etc)

9:39 blackdog: ok, thx

9:47 cemerick: rhickey: Sure -- FWIW though, file:clojure.jar!boot.clj is an absolute path, as interpreted by java.net.URL. I can certainly understand that allowing URL paths into bytecode as opposed to file paths could muck things up.

9:51 Lau_of_DK: Any of you guys know of an optimal way to approach XML handling in Clojure?

9:52 blackdog: there's an xml.clj

9:52 but i haven't looked

9:52 Lau_of_DK: k thanks, sounds like a good place to start :)

9:52 blackdog: check api page for more

9:53 Lau_of_DK: oh goodie, Chouser has already posted some stuff on it :)

9:56 blackdog: anyone using jnlp with clojure?

9:56 i never used it before, do i have to have a main-class tag in the descriptor when user.clj is run auto?

9:57 Lau_of_DK: (xml/parse "wayport.xml")

9:58 lol - its a shame when your IRC client looks to similar to your REPL that you make those kinds of mistakes :)

10:13 Am I remembering incorrectly, or was there a "loop across" functionality, that worked on hash-maps?

10:16 rhickey: cemerick: is there utility to such paths? what can you do with file:clojure.jar!boot.clj?

10:24 cemerick: rhickey: those paths aren't helpful to me, but a java debugger should have no problem yanking that resource if it's referenced in some bytecode (since remote code loading is ostensibly baked into java). The path that *is* helpful to me is an absolute path to user.clj, which would then be able to use *file* to know where it is and therefore the clojure it bootstraps from there would be able to reliably know what "root" to operate under. Right now, I'm ju

10:25 I've been harping on the absolute path bit because the scenario I just described seems like it'd be a pretty common approach. *shrug*

10:26 rhickey: cemerick: you got cut off at Right now ...

10:26 cemerick: huh... Right now, I'm just making sure my pwd is set properly; that will get replaced by some system property at startup that user.clj will pick up.

10:27 blackdog: cemerick, you could just start the jvm up in the correct root to start with, and know where you are? then use "user.dir" within the prog

10:28 cemerick: blackdog: Yeah, that's what I'm doing now.

10:31 There are definitely advantages to making environment concepts like "app root" and such localized to the code, rather than adding another requirement to the runtime configuration. That's definitely used a lot in the python world (for example), which has __file__, which is always the path of a file relative to your pwd.

10:32 rhickey: how is that not a classpath?

10:32 cemerick: rhickey: because when you load user.clj, *file* is _always_ "user.clj". It could be loading it from any of the root classpath entries.

10:33 In the python example, you can always get your absolute path with os.path.join(pwd, __file__)

10:34 rhickey: Does Pythonm handle remore code loading etc?

10:34 remote

10:35 pwd doesn't seem a very useful concept once you get into remote code, app servers etc

10:36 I understand classpath has its faults

10:36 cemerick: aside from some hackish workarounds, not to my knowledge

10:36 FWIW, I'm definitely not trying to do any direct comparisons, etc. The current situation is fine, just a little inconsistent between *file* in a load-file call and *file* when user.clj is autoloaded.

10:36 rhickey: I think a current problem is Clojure doesn't use enough of the namespace management, i.e. those clj's shouldn't be in the root

10:37 cemerick: yes, I understand

10:37 blackdog: on executing clojure from a jar file, should i include a main java stub class?

10:38 it seems forced by the manifest

10:39 or do i use a clojure main function somewhere to start things off?

10:39 rhickey: to get a stand-alone looking solution (i.e. no supplied script), you could, although the user.clj autoloading helps avoid that too. Note that gen-class can generate main now

10:40 blackdog: right now i'm trying java -cp clojure.jar app.jar with user.jar in app.jar and a stub java main

10:41 i maean user.clj

10:41 but user.clj is not (println "hello")

10:41 not unless it's a flush thing

10:41 cemerick: rhickey: BTW, I hacked together a little macro that loads and then saves a generated class in order to get around the self-referential problem mentioned yesterday. Definitely not a long-term solution, but it gets the job done (for now, and probably only for me :-) ).

10:41 blackdog: should that work?

10:45 rhickey: cemerick: ok, sorry I hadn't thought of that self--reference in the first cut

10:46 cemerick: rhickey: seriously, no need to apologize

10:47 Lau_of_DK: naah man, we all make mistakes :)

10:52 Chouser_: blackdog: I have gotten into the habit of always putting (flush) after any prn or println used for debugging. It makes things less surprising.

10:52 I dunno if it'll help in your specific case, though. :-)

10:59 cemerick: Chouser_: damn, I had always thought that println did a flush itself.

11:00 rhickey: yeah, that seems to be a frequent trip-up for people, I'm considering changing it

11:00 Chouser_: oh. well, I usually use (prn) for debugging. I'm not sure what println does.

11:01 ...so I'm back from my trip. Have we seen a flood of new users from the 8 people I talked to on Friday? No? Ah, well... ;-)

11:02 rhickey: did you have door prizes?

11:03 Chouser_: I guess I should have had a whole box of clojure T-shirts or something.

11:03 Oh. Man. We should have Clojure T-shirts.

11:03 rhickey: there you go

11:03 I have one

11:03 Ycros: I would buy one

11:04 Chouser_: does it have a snappy quip?

11:04 rhickey: from my wife - it says "You're doing it wrong" on the back

11:04 Chouser_: There you go!

11:04 really, that's perfect. You would sell a dozen, at least.

11:07 rhickey: wmorgan: (sorted-set) fixed

11:08 * drewr wants a t-shirt

11:09 cemerick: "You're doing it wrong" sounds good, although I'm currently feeling a little allergic to that sort of confidence, after watching a couple of noobs get torched in #lisp yesterday.

11:09 * cemerick still doesn't know why he has #lisp on autojoin anymore

11:10 Chouser_: yeah, it's not clear that we mean anyone *not* using Clojure. Everyone using clojure is, of course, doing it Right.

11:10 rhickey: I prefer - "State - you're doing it wrong", about which I am more confident

11:11 but, as I said, it was a gift. Clojure is generally non-confrontational

11:11 cemerick: Sure. I'm just feeling punchy today. ;-)

11:12 Chouser_: Maybe just flip it around to positive: "you can do better"

11:16 "Who knew Java could be so fun?"

11:26 cemerick: I'm just waiting for the Clojure lolcats to start making the rounds.

11:27 rhickey: lolcats?

11:28 drewr: "Java: Makes better languages than applications."

11:29 cemerick: rhickey: here's some haskell-themed ones: http://arcanux.org/lambdacats.html

11:29 rhickey: ah

11:43 rsynnott_: heheh

12:12 Chouser_: http://www.zazzle.com/state_you_re_doing_it_wrong_shirt-235609552304110841

12:12 I of course haven't bought one yet, so I have no idea what the quality is like.

12:13 ...and I'm happy to hand the password and stuff to rhickey so he can collect the proceeds if anyone buys any.

12:34 abrooks: Chouser_: No Clojure logo?

12:34 Chouser_: on the front.

12:35 want another on the back? i guess it might spice it up a little.

12:35 rhickey: chouser: cool!

12:36 albino: do you get to choose the font for that?

12:36 Chouser_: yes

12:36 I think you can customize your shirt however you want, from that link.

12:37 albino: I would so wear that shirt to some geek conference

12:38 Chouser_: Since I'm using C++ at work, maybe I need one for the office that says "State - we're doing it wrong"

12:38 albino: heh

12:38 give it to the managers and see if you can get them to wear it to meetings

12:42 Chouser_: abrooks: with a logo on the back: http://www.zazzle.com/state_you_re_doing_it_wrong_shirt-235415785053901854

12:45 rhickey: Chouser: do you need bigger images? I have 500x500 and can get larger

12:45 Chouser_: nope, thanks. That's about 500x500 already.

12:46 I've got an SVG now that seems accurate enough for whatever.

12:47 I assume 500x500 is enough for that size on a T-shirt. Whoever buys the first one can report on that.

12:47 rhickey: tomhickey: any thoughts on SVG?

12:53 Chouser_: or in black: http://www.zazzle.com/state_you_re_doing_it_wrong_black_shirt-235357523415203587

12:53 ok, that's enough. you can pick one of those or go customize it yourself.

13:02 pjb3: http://farm4.static.flickr.com/3229/2613013337_ecc41f4123_o.jpg

13:03 tomhickey_: http://groups.google.com/group/clojure/web/Clojure.svg

13:05 drewr: pjb3: Hahaha.

13:08 Chouser_: pjb3: nice

13:09 tomhickey_: thanks!!

13:09 I should have asked for that last week instead of tracing my own.

13:22 tomhickey_: Chouser_: no problem. glad i could help

13:33 rapido: i wonder if clojure has any distributed computation/data capabilities ?

13:34 rhickey: rapido: not yet

13:34 Chouser_: aren't there several Java libs that can make that happen?

13:34 rapido: rhickey: i guessed that you are thinking about it. care to share some thoughts?

13:35 i believe immutability scales very well in a distributed environment

13:35 no more stale caches

13:36 blackdog: in rhickey's concurrency talk he mentions the possibility of wrapping jms

13:36 Nafai: Hi rapido!

13:36 rapido: hey nafai - the user list shows some more concatenative :)

13:37 rhickey: there are many aspects, first is some sort of process coordination/communication, for which I am looking at Shoal

13:37 then there's distributed data/computation

13:38 I'd definitely prefer to sit on some well-regarded Java infrastructure

13:38 not interested in writing my own distributed DB

13:39 rapido: rhickey: i believe you only need to implement a distributed hash table

13:39 on that, you can build any data structure

13:40 for instance, you can overlay an immutable data structure on top of a dht

13:40 rhickey: we've discussed that here, but a distributed hash table is a big project

13:40 cemerick: FWIW, I'm leaning towards hadoop and HBase for our current project

13:41 There's already a reasonably-pleasant hadoop wrapper for clojure on the google group. The data models are nicely congruent.

13:41 rapido: there are many dht's: azureus, limewire, overlayweaver, freepastry, all of them on the jvm

13:41 Lau_of_DK: Evening gents

13:44 abrooks: rhickey: As I work for an HPC company (http://SiCortex.com) I've been thinking about Clojure's concurrency mechanisms and how they might be extended across multiple nodes. It seems like the general idea behind persistent data structures could be extended but lazy fetching would lead to unacceptable latencies and there are issues of distributed GC (not unsurmountable but issues none the less). The current concurrency ...

13:44 ... mechanisms operate on non-NUMA assumptions -- everything costs the same.

13:44 rapido: building an immutable data structure on a faulty (but redundant) dht can give you ACID properties

13:45 using some kind of MVCC or other conflict resolution methods

13:46 rhickey: so there is no need to build a distributed db yourself. just leverage on top a dht

13:46 rhickey: abrooks: It is fundamental to Clojure's model that the distributed and local models not be unified, so I expect something different will be needed for the distributed case

13:47 rapido: rhickey: i agree you can't/shouldn;t hide distance/network/etc.

13:48 like you can't hide multiple cores

13:48 behind leaky abstractions

13:49 but how should they be exposed first class?

13:50 throwing an network-exception isn't the way forward

13:50 nor hitting a stale cache entry

13:51 rhickey: I think Erlang's distributed model can't be ignored

13:51 but it is hard

13:52 rapido: rhickey: agreed, but erlang isn't exactly p2p

13:52 rhickey: i.e. it just acknowledges that distributed programming is fundamentally hard

13:53 rapido: p2p must handle faulty nodes, faulty networks, churn, byzantine problems, etc.

13:54 you shouldn't trust no one in p2p networks! tit for tat i say :)

13:55 rhickey: distributed programming IS hard, yes. erlang has a lot of right defaults

14:01 abrooks: rhickey: Right, I wasn't suggesting that the difference between fastl/local / slow/distributed be hidden but more wondering how you saw slow/distributed fitting in with the current scheme. I could see some rich proxies of refs/agents and a mechanism proxied references for distributed GC purposes being somewhat natural fits with what we have today. One thing that shouldn't be hidden is some for of eager (or limited ...

14:01 ... eager) caching of data in the reference proxying.

14:02 rhickey: All this is still preliminary, but here are some things I've been thinking about:

14:03 Erlang-like procs based upon Shoal

14:03 distributed agents also based upon Shoal

14:03 Distributed STM based upon Terracotta

14:04 abrooks: BTW, I'm sitting in USENIX talks right now and every talk is mostly centered around the issue of "How dow we make use of multiple cores? How do we scale software in a comprehensible manner?" I keep wanting to shout out "Clojure!"

14:04 rhickey: I think Terracotta could do a good job with the data structures, but the synchronization primitives were too slow last time I tried it

14:05 rapido: shoal is more like erlang, less like p2p

14:06 * abrooks has no familiarity with Shoal and only a little with Terracotta (i.e. he read a little about it)

14:06 rapido: trusted nodes

14:06 instead of faulty peers

14:06 rhickey: I had an earlier version of the Clojure STM running on Terracotta at one point

14:06 rapido: or malicious peers

14:14 drewr: abrooks: Ah, you're listening to Pratt in *person* :-)

14:15 cemerick: I'm still somewhat unclear about the use case for jvm-level clustering like Terracotta. "Transparent" distributed concurrency comes with so many potholes and (from what I've read) very little about data management.

14:16 That's all probably a function of my problem space though. :-)

14:17 rhickey: it's true that once you go distributed, there is no 'one size fits all'

14:18 some problems are mostly autonomous processes that need to communicate

14:18 some are distributed crunching, a la map/reduce

14:18 some are shared database

14:25 abrooks: drewr: ;-) The Pratt talk is over now.

14:41 cemerick: I suppose terracotta or shoal would help in building a durable message queue...

14:41 it's very hard to thing outside of one's particular box when you're deep in it :-)

14:42 rhickey: yes, and there are independent solutions for all of those specifics, including message queues, so it does beg the 'what belongs in the language' quesiton

14:47 Chouser_: rhickey: You're probably not deep into XML, but any particular reason xml/parse isn't lazy?

14:47 rhickey: maps aren't lazy

14:48 Chouser_: but the seq of children in each map could be

14:49 cemerick: rhickey: well, the huge mass of potential solutions to these problems jumping up and down, marketing themselves as the second coming makes me think that any *language-level* support is premature. Libraries are good when things are in flux.

14:49 rhickey: Chouser: with what parser?

14:50 abrooks: Chouser_: You couldn't see well formedness with a lazy parser.

14:51 Chouser_: sax parsers work with incremental input

14:52 rhickey: yes, but you are asking for delayed subtrees

14:54 Chouser_: you don't think it's possible with stock Java sax parsers?

14:54 rhickey: I have no idea - you'd have to be able to checkpoint things as you passed them, as you'd have to read the subtrees anyway in order to skip them

14:55 Chouser_: yeah. But zip and zip-filter are already lazy in this way, where they can work with parts of the tree without ever examining other parts.

14:55 if the "other parts" were later in the file, it seems like it might work.

14:56 rhickey: now if xml was a chunked data format...

14:56 Chouser_: anyway, just asking. Maybe I'll play with writing a drop-in replacement for xml/parse that's lazy.

14:56 rhickey: zip is working with a real tree

14:57 xml files become trees, but they are not trees

14:58 Chouser: it's a valid objective - I was just thinking about lazy-reading for Clojure this morning

14:59 Chouser_: I do think it'd be very easy to make a zip call (and even more so a zip-filter call) that required the whole doc to be parsed, without realizing you were requiring that.

15:22 ignore my earlier t-shirt links. Just use this one: http://www.zazzle.com/clojure

15:22 I'll shut up about them now. :-)

15:32 Lau_of_DK: Woot - How made that print?

15:32 How = Who

15:51 nobody will claim responsebility? You'd make lousy terrorists

15:52 (oops, I might have crashed an Echelon server)

15:54 Chouser_: Lau_of_DK: I think pjb3 made the poster, if that's what you're talking about.

15:55 pjb3: What, the automotivator? Yeah, that was me

15:59 Lau_of_DK: What is an automotivator?

16:00 Chouser_: Lau_of_DK: http://wigflip.com/automotivator/

16:02 Lau_of_DK: Nice work pjb3, but because with harassing the Pope

16:03 pjb3: harassing the Pope? Are we talking about the same thing? http://farm4.static.flickr.com/3229/2613013337_ecc41f4123_o.jpg

16:03 Lau_of_DK: haha, no I wouldnt go that far about Rich

16:04 http://images.wigflip.com/funny.jpg

16:05 Chouser_: Lau_of_DK: I don't think that worked like you meant.

16:06 Lau_of_DK: Chouser: What do you mean ?

16:06 Chouser_: You just posted a plain picture of the pope. Is that what you meant to do?

16:07 rhickey: The pope is OT for Clojure :)

16:07 Lau_of_DK: Yes sir... My point was this, at the wigflip.com/automotivator page, the picture of the pope is suggested, and I was just saying that something like that usually sends sparks flying - thats all

17:22 cemerick: rhickey: Back to the gen-class stuff. Would it also be possible to provide the name of the class to be generated by gen-class as a symbol? Doing so would allow gen-class to be totally independent of the state of the runtime, which would eliminate the possibility of any cyclic dependencies between Java code and referenced gen-classed classes.

18:01 rhickey: cemerick: yes, that's how it will work when I get back to it

18:02 cemerick: rhickey: fantastic. That makes life a lot easier.

23:10 Chouser: bah. so the SAX parser expects a blocking reader. It won't return until the Reader is done.

23:10 I think that means the only way to make it lazy is to pack it off into its own thread.

Logging service provided by n01se.net