#clojure log - Jul 02 2008

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

1:27 Lau_of_DK: How do I compile my .clj file into a singla .jar file?

1:27 (replace \a \e)

1:29 How do I compile my .clj file into a singlr .jar file?

1:30 (replace \r \e)

1:44 k, nobody knows... When we refer to Trees, are we generally talking about hash-maps?

2:44 perspectivet: quick newbie question

2:45 how do I replicate c-style "while( x() ) { y(); }?

2:46 Lau_of_DK: Check the loop / recur documentation

2:47 (loop [x y z] ( x() y() (recur (new x) (new y) (new z))

2:49 cgrand: perspectivet: can you give more details on what you try to achieve? In FP most functions take arguments and those which don't are constant.

2:51 perspectivet: I'm tranlating the following swt snippet into clojure

2:51 ;; Display display = new Display ();

2:51 ;; Shell shell = new Shell (display);

2:51 ;; Text text = new Text (shell, 0);

2:51 ;; text.setText ("ASDF");

2:51 ;; text.setSize (64, 32);

2:51 ;; text.selectAll ();

2:51 ;; shell.pack ();

2:51 ;; shell.open ();

2:51 ;; while (!shell.isDisposed()) {

2:51 ;; if (!display.readAndDispatch ()) display.sleep ();

2:51 ;; }

2:51 ;; display.dispose ();

2:52 cgrand: ok, I'm reading it (next time use http://paste.lisp.org/new/clojure for pasting code)

2:52 perspectivet: sorry

2:53 will do

2:54 lisppaste8: perspectivet pasted "swt snippet tranlation" at http://paste.lisp.org/display/63147

2:54 perspectivet: that's things so far

2:55 cgrand: ok: java interop so FP rules don't apply there :-) In that case loop/recur is the simplest way to go

2:56 perspectivet: cgrand: yeah, I figured. I'm coming over from the haskell world as far as recent fp experience goes and I couldn't find an api for any of the approaches I would use there.

2:58 lisppaste8: cgrand annotated #63147 with "added translation for the while" at http://paste.lisp.org/display/63147#1

3:01 cgrand: perspectivet: so as you can see my answer to your original question is (loop [] (when (x) (y) (recur)))

3:08 jgrant: cgrand : do you know of a way to create a jar of a clojure script/s ?

3:14 Lau_of_DK: Quoting cgrand

3:15 for the jar file structure: copy clojure.jar and

3:15 open it, name you main file "user.clj" and put it in the directory where boot.clj is. Edit

3:15 the manifest file to point to clojure.lang.Script instead of clojure.lang.Repl as the main

3:15 entry point for the jar.

3:15 if you havce to load other files from

3:15 user.clj, use (. clojure.lang.RT loadResourceScript "xxx.clj")

3:16 jgrant: thx

3:16 perspectivet: on a related note, is there a way to standard way to ship compiled clojure files?

3:17 btw: thx cgrand

3:17 jgrant: yea where are the compiled class files that clojure generates ?

3:18 (seems like that would be a much 'saner' approach)

3:21 Lau_of_DK: I dont know - I would like to know,Im missing (save-lisp-and-die)

3:22 jgrant: now if only sbcl was as stable as the jvm ;)

3:23 perspectivet: is there an emacs mode with automatic-paste-lisp-org-paste or somesuch?

3:53 cgrand: jgrant: compiled class are never written to disk (except for genclass) and even if they were, they wouldn't be usable as-is because there's some close cooperation (can't give more details: I'm not Rich) between the class loader and the class to close over the environment

3:56 hoeck: mhh, would it be possible to save an image of the jvm?

4:12 Lau_of_DK: Theoretically at least, it should be possible

4:22 cgrand: hoeck: volunteering to test how http://cryopid.berlios.de/ interacts with the JVM? ;-)

4:25 Lau_of_DK: cgrand, that looks sweet, but its not fully ready yet, would you mind finishing it, so we can toy with it tonight?

7:56 cemerick: Am I right in thinking that it's totally OK to throw an UnsupportedOpEx from ISeq.cons?

8:14 rhickey: what seq doesn't support cons?

8:22 cemerick: deriving from clojure.lang.ASeq will give you cons and much more for free

8:25 cemerick: rhickey: A half-hour ago, I hadn't noticed ASeq :-)

8:26 but, FWIW, it doesn't make sense to cons onto this particular seq (a resultset of sorts -- not from a SQL query, but similar in concept)

8:27 rhickey: yeah, someday there will be JavaDoc... until then, everyone should be aware there are abstract helper bases for most of the persistent data structures

8:28 cemerick: the sensibility seems, to me, to be in the eyes of the conser, not the consee

8:29 cemerick: rhickey: True enough. That's sometimes hard to see when one is playing both sides of the fence.

8:29 rhickey: :)

8:48 cemerick: This might be unreasonable given the current impl, but would be nice in some circumstances to have full destructuring available in def.

8:48 s/would/it would

8:48 rhickey: in order to def more than one thing at a time?

8:57 cemerick: rhickey: Yeah, I have a couple of situations where I'm doing stuff like (let [{foo :foo bar :bar baz :baz} (getEnvironmentInfo)] (def foo foo) (def bar bar) (def baz baz)). I fooled around with a couple of macros, but anything short of reimplementing destructuring in them would lead to a crippled result (I think :-) ).

8:58 It's an infrequent pattern, of course, so it may not be worth thinking about too much.

9:01 rhickey: destructuring is available a la carte:

9:01 user=> (destructure '[[a b] x])

9:01 [vec__2149 x a (clojure/nth vec__2149 0 nil) b (clojure/nth vec__2149 1 nil)]

9:01 user=> (destructure '[{:keys [a b]} x])

9:01 [map__2150 x a (clojure/get map__2150 :a) b (clojure/get map__2150 :b)]

9:06 cemerick: Very nice.

9:06 That's not in the docs anywhere, though -- I guess only defns that have docstrings make it in.

9:07 scgilardi: The ns-utils lib has a "vars" command that displays all the vars defined in a namespace. (vars clojure) is good to peruse from time to time.

9:09 rhickey: not doc'ed because I don't want to guarantee its interface yet, but it's stable, and obviously used often by Clojure

9:09 cemerick: rhickey: Sure, wasn't saying it should be doc'ed. Just happy I didn't pass over it.

9:09 rhickey: you could easily write a destructuring-def with it

9:10 one trick about it is that it will return its argument if no destructuring was needed

9:11 cemerick: I might get around to it. The stuff that uses let for destructuring is put to bed at the moment.

9:12 scgilardi: BTW, thanks very much for the lib tweaks (and pred as well...no need to keep carrying around our own similar utils anymore).

9:13 scgilardi: you're quite welcome. I'm glad you're finding them useful.

9:13 blackdog: scgilardi, where is this library?

9:14 i don't see one by you in the Files section

9:14 scgilardi: http://clojure-contrib.svn.sourceforge.net/viewvc/clojure-contrib/

9:14 blackdog: ah, didn't know about that

9:14 thx

9:15 cemerick: Yeah, it took me a minute to look in svn, too. :-)

9:15 scgilardi: clojure contrib has some cool stuff in it from a few folks :)

9:15 blackdog: neat, i thought everything of use was on the google group

9:16 rhickey: I'm hoping to fold some of the great stuff from contribs into Clojure soon after ECOOP next week

9:16 scgilardi: very cool. have a great trip. are you presenting anything?

9:18 rhickey: Yes, I'm presenting twice, once to the European Lisp Workshop on the Lisp nature of Clojure, and once at the Dynamic Languages Symposium on Clojure generally

9:19 towards the end of incorporating contribs, I have been looking at adopting Sun's contributor agreement for Clojure: http://www.sun.com/software/opensource/contributor_agreement.jsp - any thoughts

9:19 ?

9:19 scgilardi: nice (re: presentations). I'll check out the website to see if they make videos or transcripts available.

9:24 rhickey: the main purpose of the SCA for Clojure would be to prevent it from becoming license-bound, i.e. everyone contributed under license X, preventing the project from moving to license Y, or X + Y. I like it because contributors give up none of their own rights

9:26 scgilardi: yes, it does seem like a light touch with the main goal of sharing the copyright on contributions. Sounds good to me.

9:54 Chouser: The SCA looks pretty good. I can't seem to find much meaningful critisizm of it, which is impressive for the kind of role it plays.

9:56 rhickey: It originally got bashed for not having the "Any contribution we

9:56 make available under any license will also be made available under a suitable FSF (Free Software Foundation) or OSI (Open Source Initiative) approved license." language

10:01 Chouser: yep, I saw that, and it's a good clause to include.

11:10 cemerick: ffailla: Any news vis a vis Shoal on ikvm?

11:31 Lau_of_DK: Anybody up for tag-teaming on a quick 'n' dirty Clojure-IRC client ?

11:34 Chouser: ajax?

11:35 Lau_of_DK: swing?

11:36 Chouser: ncurses?

11:36 Lau_of_DK: Why not swing?

11:36 Chouser: :-) I guess my answer is "not really".

11:36 Lau_of_DK: oh

11:37 Would have been fun to tag-team with the infamous CHOW-zarrrrrrr

11:37 But I'll let you go

11:37 Chouser: heh.

11:37 what do you mean by "tag-team" specifically?

11:38 Lau_of_DK: I'll fill you in a little later, dinners served. But I was thinking that we divide the tasks, quickly get something working, if somethings too difficult or not done well enough, clap each others hands and switchs jobs :)

11:40 Chouser: hm, interesting.

11:43 cemerick: sounds like the start of a clojurebot :-)

11:45 Chouser: hm, now that might be interesting.

11:58 cemerick: Am I right in thinking that currently the most idiomatic way of yielding a seq without an item is to filter?

12:11 Chouser: I guess it depends on how you know which item you don't want.

12:17 (filter (complement #{:c}) [:a :b :c :d :e]) ==> (:a :b :d :e)

12:17 (filter #(not= % :c) [:a :b :c :d :e])

12:18 (for [i [:a :b :c :d :e] :when (not= i :c)] i)

12:19 (disj (set [:a :b :c :d :e]) :c) ==> #{:b :d :e :a}

13:46 rhickey: (set/difference #{:a :b :c :d :e} #{:c})

13:50 Chouser: (reduce #(if (= %2 :c) %1 (conj %1 %2)) [] [:a :b :c :d :e])

13:52 cemerick: so, do you have the value of the thing you want to remove, as all these examples assume? Or do you have its index?

13:53 cemerick: Chouser: sorry, disappeared for a bit. Yeah, I always have the thing I want to remove. I guess I'm thinking that a complement to conj would be handy.

13:54 rhickey: unj?

13:54 Chouser: ha!

13:54 rhickey: lists -> pop, set -> disj, map-> dissoc

13:55 but remove from middle of list is not opposite of conj

13:55 Chouser: you might have duplicates in your seq, though, so you might want to be able to take from either end. like unj-early

13:55 and unj-late

13:55 cemerick: True, true. Just talking into the wind, as usual. :-)

13:55 Chouser: cemerick: would your seq be better as a set?

13:56 cemerick: Unfortunately not.

13:56 Lau_of_DK: rhickey: Im considering doing a simple IRC client (swing) in Clojure - Have you got any insights to share _before_ I lay the foundation ?

13:56 * rhickey first tried irc after someone else created #clojure

13:57 cemerick: I already have a remove-one function that uses lazy cat to avoid consing up the rest of a seq after an item's been removed.

13:57 Lau_of_DK: Oh.

13:57 :)

13:58 cemerick: I'm just always looking for the cleaner, more applicable solution. :-)

13:58 Lau_of_DK: Could you then tell me if there's any networking helpers thought into clojure, or if its going to be pure java interop ?

13:58 Chouser: cemerick: the file and for examples above are fully lazy

13:58 er, "filter" and "for"

14:02 rhickey: Lau_of_DK: I would just grab a Java IRC lib and use it

14:03 Lau_of_DK: Okay

14:03 I'll look into those - Have you checked out MigLayout rhickey ?

14:03 rhickey: no

14:04 Lau_of_DK: Its works very well with Clojure for making Swing applications, you can set up "complicated" GUIs with event handlers and everything in very few lines of code

14:04 pjb3: So as it turns out, there is an even better solution to Concurrency than Immutability, and that is to have no shared state

14:05 This seem to me to be very common in J2EE web applications

14:05 Chouser: pjb3: with a relation database as the only shared data?

14:05 relational

14:05 pjb3: You have Servlets, JSPs, access to a database via JDBC, and frameworks built on top of those

14:05 Chouser: yeah, and the only shared data is in the database

14:06 I bring this up to discuss the whole "State, you're doing it wrong thing"

14:06 and I think a valid response to that is

14:06 "No I'm not, I'm not sharing any data across threads"

14:07 In other words, whether it be a J2EE app, or Ruby on Rails, or whatever, if you are building a web app that talks to a database, concurrency really isn't an issue, is it?

14:07 rhickey: Not doing state at all is perfectly fine - the tools are for when you need state

14:08 pjb3: rhickey: Sure, and the only reason I bring all this up

14:08 rhickey: pjb3: it is for the guys writing the appserver you're running on, or the database

14:08 pjb3: is that what I am finding, the more I work with Clojure

14:09 the more I like it

14:09 but it is for all sorts of other, non-concurrency related things

14:09 rhickey: I think one of the saddest things I see is when people pull data from a db and stick it in a mutable object

14:09 pjb3: and all these things should be mind-blowing to J2EE web app developers

14:10 rhickey: so that's pretty common in web apps, what's sad about it

14:10 * pjb3 is asking, not challenging your opinion

14:11 rhickey: why mutable? blows the functional/relational model

14:11 pjb3: not sure what you mean by functional/relational model

14:12 Chouser: I suspect that as web apps take more advantage of ajax and especially comet-like stuff, databases become less sufficient as the only state.

14:12 rhickey: the pervasive caching says that's already the case

14:13 pjb3: you just touted the db as the only state, with a mutable object you've now got your state back

14:13 Chouser: imagine a chat server -- with polling, a db might be okay, but with comet you'd like to send a message across to another session. Suddenly you've got in-memory multithreaded state.

14:13 rhickey: db has state != app is single threaded

14:14 Chouser: rhickey: yes. did I imply otherwise?

14:14 rhickey: apps may need to leverage multiple cores to speed up any calculation

14:14 Chouser: sorry, that was for pjb3

14:15 Chouser: ok

14:15 * rhickey doesn't know how to grab nick's in his irc client without mouse selection

14:16 pjb3: rhickey: The mutable object is essentially a read-only copy, if you want the changes to persist, you call methods on the object to modify the data, and eventually the object generates a SQL update statement to put the new state of object into the db

14:16 Chouser: I hope to do some tests and performance tuning on the lazy xml stuff tonight. It seems to me that it ought to be nearly as fast worst case as xml.clj, and if you have multicores or can take advantage of laziness, significantly faster.

14:16 rhickey: you can't just start the nick and press <tab>? what client?

14:17 rhickey: Chouser: thanks!

14:17 Chouser: :-) np.

14:17 pjb3: and AFACT, that's really no different that querying for data, storing it in an immutable map, creating a new, slightly different immutable map based on that, and then generating a SQL update to store that

14:17 rhickey: pjb3: it's way different

14:18 Chouser: surely if the mutable object is only within a single thread, it's only slightly different?

14:19 rhickey: It's way different because in one case you can add another thread without a rewrite, reuse the same logic in other MT apps, test without mocks and setup etc etc

14:20 Chouser: the lazy xml is really neat, but the *enqueue* and esp. exceptions for flow control really bother me - is there no other way?

14:22 Chouser: I don't think there's any way around *enqueue* (or some other acts-like-mutable thread-local binding) without bringing in an new xml parser API (such as a pull parser). Even the existing xml.clj has a pile of thread-local bindings.

14:23 rhickey: Clojure was born in part due to the extreme pain I saw endured over and over when code that would 'only run with one thread' had MT added

14:23 Chouser: The exception is a little messy, but it's not really for flow control. It's only used to kill off an abandoned parser thread. Perhaps I could kill the thread some other way? Again, bringing in a pull parser would solve this.

14:23 pjb3: rhickey: web apps are MT, they just don't share state between threads

14:24 rhickey: maybe not today, but that is, IMO, a false presumption moving forward

14:26 pjb3: and the easiest way not to share state is to not have it, e.g. use immutable data structures

14:29 Chouser: I've been thinking a lot about seqs on stateful things, this queue thing is just another variant of the auto-closing stream requests

14:29 same problem - dangling non-memory resource

14:34 drewr: Chouser: Is that double LET in your CASE macro a common idiom?

14:34 (With the GENSYM..)

14:35 Chouser: rhickey: that's a good point. your weak-ref solution might be the key.

14:35 drewr: dunno.

14:36 rhickey: Chouser: I did a lot of testing and was frustrated by the unpredictability of weak-ref reclamation

14:37 Chouser: drewr: probably not uncommon though in a macro. the outer let is just for while the macro's expanding. The inner let is in the expanded code.

14:37 rhickey: sometimes threads came right back, other times they stayed around indefinitely

14:38 Chouser: rhickey: yeah, I was surprised to see at least one of those threads hang out for a few minutes with everything in the JVM idle.

14:38 but that's the flip side of the ethereal GC you like so much, isn't it?

14:39 rhickey: Chouser: not really, we're trying to tie something non-memory to memory

14:40 Chouser: and I think the problem is when it gets moved to another generation - real ephemeral memory doesn't get there

14:40 drewr: Chouser: Just seem strange to do in two LETs what I would think you wouldn't need to do at all. val already has a binding from the enclosing scope.

14:41 rhickey: Chouser: my latest thinking is possibly to have LazySeq implement Closeable, and lazy-cons take an optional third on-eos expression

14:41 Chouser: drewr: the inner let is common. I could have done without the outer let and just used val# if I hadn't done two separate `() exprs

14:44 Hm, apparently doto in boot.clj uses the same idiom for essentially the same reason.

14:45 * Chouser reads about Closeable

14:46 rhickey: Chouser: sure, nothing wrong with that - ` and blah# are convenience features with limits

14:48 Chouser: so what would call LazySeq's close method? Does Java do that automatically?

14:49 rhickey: Chouser: no, you'd use the with-open idiom

14:49 plus auto-close on eos

14:50 There isn't a way to let someone off the hook from knowing they're holding a resource

14:51 could use dynamic var to free from manual registration: (closing-all ...)

14:52 Chouser: but you certainly don't want to have to use with-close on all seqs just in case they might have some special resource that needs closing.

14:52 rhickey: where resources would register with *auto-close*

14:53 Chouser: no, but there's no free lunch either

14:53 Chouser: but you're so close with weakrefs! :-)

14:53 rhickey: finalization is a bad hook

14:54 Chouser: just as laziness can be passed up through a series of wrapped seqs, so would the need to use with-close.

14:55 rhickey: Chouser: I understand, but in the end what you are asking for is the messy stateful world to be as elegant as the beautiful lazy functional world, and it simply can't

14:57 pjb3: Are there docs on how to use clojure from within a java app?

14:57 Chouser: yeah, I guess the reason it hurts so much in my case is that the XML parser really doesn't need to be stateful, so I was nearly able to abstract away the statefulness. ...but not quite.

14:58 or rather encapsulate it fully. but not quite...

15:00 rhickey: Chouser: the queue problem has a different formulation, where consuming from the queue fires off a one-shot agent request to put more in, but doesn't help your event-driven parser problem

15:02 Chouser: you're saying seque has the thread resource issue regardless of how the queue is filled? of course you're right.

15:04 pjb3: If I want to use clojure from within a servlet, what do I need to initialize Clojure?

15:04 If I pass a String to clojure.lang.Compiler.eval, it throws a Null Pointer Exception

15:05 Chouser: eval wants a datastructure, not a string.

15:05 but that's not the right direction anyway

15:05 hang on, looking for a link...

15:05 rhickey: Chouser: no, the opposite, I think my original seque can be done with no hanging thread by sending after each take, rather than dedicating a filler...

15:05 pjb3: Chouser: thanks

15:06 rhickey: Chouser: but an event-driven SAX parser requires a dedicated thread and state

15:06 Chouser: pjb3: http://clojure-log.n01se.net/date/2008-06-28.html#10:44b

15:08 rhickey: ah! yes of course! seque could send-off to get n ahead, and then send-off again once per consumer request.

15:08 rhickey: right

15:08 each send would fill as much as possible then quit

15:09 Chouser: yeah, which would completely solve the resource issues with all seque's except for mine. :-)

15:09 rhickey: sorry :(

15:09 Chouser: stupid sax

15:11 well, parallel.clj requires an external jar. I guess lazy-xml could require http://www.extreme.indiana.edu/xgws/xsoap/xpp/mxp1/index.html

15:11 rhickey: can you pause the sax parser in a handler?

15:12 Chouser: yes. I do that now by calling *enqueque*, which blocks.

15:12 rhickey: no, I mean tell the sax thingy to pause, and call resumeParse later

15:14 Chouser: I don't think so. I think the problem is that the sax parser's own state is just on the stack, and it sits there calling down into the handlers.

15:14 it doesn't have a way to bundle it's state to resume later. Let me check the API again.

15:15 rhickey: ok. but even a pull parser will put you in the auto-close camp

15:17 Chouser: well, I guess I'll have a file or network reader at the bottom that might need to be closed, but I don't think the pull parser would add requirements above that.

15:17 rhickey: right

15:19 Chouser: but that's fine. the user of my parser api will give me the reader and will be responsible for closing it, just like they are now with xml.clj.

15:20 each call to "rest" on my parser seq translates to a call to .next on the pull parser

15:20 rhickey: no doubt, a pull parser is a better fit

15:23 Chouser: I guess I could provide a clumsy solution with the built-in sax parser, but provide an identical api to allow switching to a pull parser.

15:23 the former would have to do *enqueue* and all the rest, the latter could use whatever seque you settle on.

16:44 cemerick: pjb3: you were asking about an error starting the REPL in enclojure earlier...

16:44 pjb3: There's a couple of patches on the enclojure google group that fix that (at least for me)

16:46 pjb3: cemerick: ok, I'll take a look at that, thanks

17:49 abrooks: rhickey: Chouser told me I should be participating in the above discussion.

17:50 rhickey: I was going to bring up a related topic the other day when I was mentioning remote concurrency.

17:52 I've been thinking about some sort of proxying object (or perhaps other mechanism -- a proxying object was a convenient way to think about this) which would allow lazy high-latency objects to work ahead a bit in a separate thread.

17:53 The proxying object would be application and object type specific to suit different performance / overhead tradeoffs.

17:56 The parser is a good example (I've not read all of the above yet...) but I've been picturing this sort of mechanism applying to any case where a lazy object incurrs high in-line latency penalties such as stream / file or remote object access.

17:57 It would be nice to be able to take an object and tell it (not sure how -- special method?) to use function X to determine how far ahead to work. The default function would simply never work ahead.

17:59 My appologies if the above is completely unclear -- my blood sugar crashed about 15 minutes ago and my head is spinning. Now I get to try to drive home through the rain like this... :)

17:59 rhickey: I'll drop in here later to clarify and talk more about this.

18:05 pjb3: If I type gen-and-save-class at the REPL, I get an exception, unable to resolve symbol

18:10 rhickey: abrooks: have a look through yesterday's log - we were talking about seques, also: http://groups.google.com/group/clojure/browse_frm/thread/e7f4de566eddb6ea#

19:01 lisppaste8: pjb3 pasted "HelloWorldServlet" at http://paste.lisp.org/display/63177

19:02 pjb3: The above pastie generates the HelloWorldServlet class file, but when I run it in an app server, it doesn't appear that those methods get called

19:02 rhickey: pjb3: nice aquamacs screencast - thanks!

19:02 pjb3: oh, thanks, no problem

19:03 init-void, that should override the public void init() method, right?

19:03 rhickey: yes

19:04 pjb3: hmmm...doesn't seem to work

19:04 rhickey: no errors loading servlet?

19:04 pjb3: no errors

19:05 I can see the log message from the app server that it is initializing my HelloWorldServlet

19:05 rhickey: com.paulbarry.HelloWorldServlet.clj is in classes/com/paulbarry/ next to the .class file?

19:05 pjb3: oh, no it isn't

19:07 unable to resolve gen-and-save-class

19:07 that's progress

19:07 I suppose I just need to make sure that gets loaded in HelloWorldServlet.clj

19:07 rhickey: you probably want the gen-and-save-class in a different file or in a comment, you don't want to run that when the servlet runs

19:07 pjb3: yeah, good point

19:08 rhickey: that's a one-time thing

19:09 jgrant: rhickey: rich, is there anything equivalent to sbcl's save-lisp-and-die function ?

19:09 or some way to package everything up in a jar ?

19:09 rhickey: not if that does what I think it does

19:10 Clojure does no ahead-of-time compilation at this point

19:10 and serializing the state of Java is not going to happen

19:11 jgrant: yea i can see why

19:11 serializing state is less important to me personally, i'm trying to figure out a way to package a clojure app as a jar

19:12 rhickey: other than jar?

19:12 jgrant: no

19:13 rhickey: with the .cljs and clojure.jar - user.clj should autoload, I guess what's missing is main?

19:13 jgrant: was just about to say that

19:34 is it possible to read user.clj from another jar (say user.jar) instead of from the file system ?

19:35 rhickey: have you tried putting user.clj next to boot.clj in clojure.jar?

19:36 user.clj will be found on the classpath

19:37 jgrant: that's what i gathered from read loadResourceScript

19:38 Why would java -cp user.jar -jar clojure.jar not work ?

19:40 rhickey: http://forum.java.sun.com/thread.jspa?threadID=657160&messageID=3882114

19:47 jgrant: thx but using the -jar switch disables -cp (uggh)

19:47 this works ...

19:47 java -cp user.jar:clojure.jar clojure.lang.Script

19:49 what's the idiomatic equivalent of common lisp's "collect" ?

19:51 rhickey: collect is a loop keyword - no loop in Clojure. you can reduce to build up results

20:05 jgrant: cool - this seems to do the trick ...

20:05 (reduce (fn [x y] (conj x y)) '(0) '(1 2 3 4 5) )

20:06 (i guess that's one possible definition of collect for clojure)

20:26 is there an equivalent of the mod operator in clojure ?

20:26 pjb3: jgrant: you know you can write that as (reduce #(conj %1 %2) '(0) '(1 2 3 4 5) )

20:27 (rem 5 2 )

20:27 jgrant: thx

20:27 and yea

20:43 rhickey : only one problem with this --> java -cp ../user.jar:../clojure.jar clojure.lang.Script -- hello

20:43 *command-line-args* is nil

20:53 slava: rhickey: do you have a way of wrapping an Iterator in a seq?

20:55 rhickey: slava: yes, that happens automatically, iterators, enumerations, Iterables, strings, arrays and all Clojure collections support seq

20:57 Chouser: rhickey: you're not working on seque, right? I thought I might try to implement your ideas from today.

20:58 rhickey: go for it

20:58 slava: rhickey: sorry, i wasn't clear

20:58 rhickey: i meant where in the source is it implemented (if it is, which it is)

20:59 meredydd: rhickey: If you wanted to make something that supported the (seq) operation, would the simplest thing just be to derive Iterator?

20:59 rhickey: slava: clojure.lang.RT.seq()

20:59 slava: cool thanks

20:59 rhickey: meredydd: the simplest way is to use lazy-cons

21:00 meredydd: if you need a class, deriving from clojure.lang.ASeq is the best route

21:00 meredydd: rhickey: Ah, yes...but I'd like it to behave as something else until (seq) gets called on it

21:00 slava: a cool project for an aspiring hacker would be a clojure-like language that compiles natively using llvm.

21:01 meredydd: ASeq sounds promising. Thanks!

21:02 rhickey: slava: are there many libs for llvm?

21:03 slava: llvm is a codegen library

21:04 rhickey: slava: right, so you'd have next-to-nothing to build on?

21:05 slava: well, if all the libraries written in C count as "next-to-nothing", yes :)

21:09 rhickey: slava: it seems tediously low-level

21:10 slava: some people are interested in compiler implementation

21:11 * rhickey is so happy to have HotSpot :)

21:12 slava: hotspot is not the last word in compilers, though

21:13 jgrant: right but the jvm was really designed/implemented in the beginning by people like Steele, Gabriel, Gosling etc.

21:13 rhickey: no, but it begs the question as to whether people should be working on per-language compilers or hotspots

21:14 jgrant: the highest volume sites on the web run on vms not in native code

21:14 slava: jgrant: the jvm compiles to native code so that's a moot point

21:14 jgrant: 18:12 <slava> jgrant: the jvm compiles to native code so that's a moot point

21:14 slava: a better argument is that the highest volume sites on on languages with gc, which makes perfect sense to me

21:15 nobody wants to manage memory mnually when they really want to be working on their web site

21:15 jgrant: yea yea everything 'compiles' to native code

21:15 slava: jgrant: not interpreters :)

21:15 rhickey: much more leverage from building a hotspot than an optimizing compiler for language X

21:15 jgrant: technically even interpreters do

21:15 slava: hotspot is an optimizing compiler for jvm bytecode

21:15 jgrant: just a matter of word games

21:15 slava: jgrant: not really

21:16 there is a distinction between interpreting a sequence of instructions and generating code which performs the same operations

21:16 jgrant: translation/compilation aside interpreters/compilers still need to run some machine code

21:16 yes yes

21:17 slava: a compiled program runs machine code generated by the compiler, an interpretd program runs the machine code of the interpreter itself

21:19 jgrant: either way the result is still machine code

21:19 is it not ?

21:20 slava: of course in the end the cpu is running machine code, but the distinction between compilers and interpeters is a useful one anyway

21:20 jgrant: i for one would love it if my cpu understood english

21:20 rhickey: jgrant: no, the distinction matters - is the CPU executing the user's code or the interpreter writer's code

21:20 jgrant: yes it's useful no doubt

21:21 the interpreters code is still modified by the script being interpreted to a large degree and influences the actual machine code being executed

21:21 anyway

21:22 rhickey: jgrant: you're never going to satisfy compiler writers with that interpretation :)

21:23 jgrant: rhickey: you are right ! and I'm going to give up I swear :)

21:30 slava: personally i'm just interested in implementation and design of compilers

21:30 if i wasn't, i'd be using hotspot, llvm, or compiling to c

21:31 rhickey: slava: fair enough

21:34 jgrant: slava : cool, i personally favor vms just because of the space i find myself working in mostly these days, i'm completely biased

22:30 Chouser: I am not truly interested in the implementation or design of compilers, so I'm happy to have rhickey. I just want to us a good language.

22:31 s/to us/to use/

22:46 rhickey: if the LBQ id not limited, the producer would now always do all the work to the end of the seq, even if the consumer loses all reference to it.

22:46 vs. your latest seque that might notice vie the weakreference that it can give up before the end even with an unlimited LBQ.

23:04 rhickey: Chouser: if the LBQ is not limited, it will be because there aren't memory issues with fully loading it

23:04 Chouser: true, but if production is CPU intensive it can hog that resource.

23:05 but I guess if that's a problem, you should limit your queue.

23:05 rhickey: just another reason to limit the LBQ - unlimited is ppretty risky

23:05 Chouser: good point

23:05 rhickey: right you are :)

23:06 Chouser: maybe unlimited shouldn't be the default

23:07 rhickey: I kept taking it out of mine...

23:09 forget now why I put it back, I think it was just the 'I know this will fit, but not exactly how big it is' scenario

23:09 gotta run

23:09 Chouser: if your producer is, say, network bound and you intend to end up with it all cached in a seq anyway...

23:09 ok, see ya

23:24 does anyone know if bopping in and out of try blocks is expensive?

23:27 as in, is it much worse to put the try block inside a loop rather than outside?

Logging service provided by n01se.net