2008-07-02
| 01:27 | Lau_of_DK | How do I compile my .clj file into a singla .jar file? |
| 01:27 | Lau_of_DK | (replace \a \e) |
| 01:29 | Lau_of_DK | How do I compile my .clj file into a singlr .jar file? |
| 01:30 | Lau_of_DK | (replace \r \e) |
| 01:44 | Lau_of_DK | k, nobody knows... When we refer to Trees, are we generally talking about hash-maps? |
| 02:44 | perspectivet | quick newbie question |
| 02:45 | perspectivet | how do I replicate c-style "while( x() ) { y(); }? |
| 02:46 | Lau_of_DK | Check the loop / recur documentation |
| 02:47 | Lau_of_DK | (loop [x y z] ( x() y() (recur (new x) (new y) (new z)) |
| 02: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. |
| 02:51 | perspectivet | I'm tranlating the following swt snippet into clojure |
| 02:51 | perspectivet | ;; Display display = new Display (); |
| 02:51 | perspectivet | ;; Shell shell = new Shell (display); |
| 02:51 | perspectivet | ;; Text text = new Text (shell, 0); |
| 02:51 | perspectivet | ;; text.setText ("ASDF"); |
| 02:51 | perspectivet | ;; text.setSize (64, 32); |
| 02:51 | perspectivet | ;; text.selectAll (); |
| 02:51 | perspectivet | ;; shell.pack (); |
| 02:51 | perspectivet | ;; shell.open (); |
| 02:51 | perspectivet | ;; while (!shell.isDisposed()) { |
| 02:51 | perspectivet | ;; if (!display.readAndDispatch ()) display.sleep (); |
| 02:51 | perspectivet | ;; } |
| 02:51 | perspectivet | ;; display.dispose (); |
| 02:52 | cgrand | ok, I'm reading it (next time use http://paste.lisp.org/new/clojure for pasting code) |
| 02:52 | perspectivet | sorry |
| 02:53 | perspectivet | will do |
| 02:54 | lisppaste8 | perspectivet pasted "swt snippet tranlation" at http://paste.lisp.org/display/63147 |
| 02:54 | perspectivet | that's things so far |
| 02:55 | cgrand | ok: java interop so FP rules don't apply there :-) In that case loop/recur is the simplest way to go |
| 02: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. |
| 02:58 | lisppaste8 | cgrand annotated #63147 with "added translation for the while" at http://paste.lisp.org/display/63147#1 |
| 03:01 | cgrand | perspectivet: so as you can see my answer to your original question is (loop [] (when (x) (y) (recur))) |
| 03:08 | jgrant | cgrand : do you know of a way to create a jar of a clojure script/s ? |
| 03:14 | Lau_of_DK | Quoting cgrand |
| 03:15 | Lau_of_DK | for the jar file structure: copy clojure.jar and |
| 03:15 | Lau_of_DK | open it, name you main file "user.clj" and put it in the directory where boot.clj is. Edit |
| 03:15 | Lau_of_DK | the manifest file to point to clojure.lang.Script instead of clojure.lang.Repl as the main |
| 03:15 | Lau_of_DK | entry point for the jar. |
| 03:15 | Lau_of_DK | if you havce to load other files from |
| 03:15 | Lau_of_DK | user.clj, use (. clojure.lang.RT loadResourceScript "xxx.clj") |
| 03:16 | jgrant | thx |
| 03:16 | perspectivet | on a related note, is there a way to standard way to ship compiled clojure files? |
| 03:17 | perspectivet | btw: thx cgrand |
| 03:17 | jgrant | yea where are the compiled class files that clojure generates ? |
| 03:18 | jgrant | (seems like that would be a much 'saner' approach) |
| 03:21 | Lau_of_DK | I dont know - I would like to know,Im missing (save-lisp-and-die) |
| 03:22 | jgrant | now if only sbcl was as stable as the jvm ;) |
| 03:23 | perspectivet | is there an emacs mode with automatic-paste-lisp-org-paste or somesuch? |
| 03: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 |
| 03:56 | hoeck | mhh, would it be possible to save an image of the jvm? |
| 04:12 | Lau_of_DK | Theoretically at least, it should be possible |
| 04:22 | cgrand | hoeck: volunteering to test how http://cryopid.berlios.de/ interacts with the JVM? ;-) |
| 04: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? |
| 07:56 | cemerick | Am I right in thinking that it's totally OK to throw an UnsupportedOpEx from ISeq.cons? |
| 08:14 | rhickey | what seq doesn't support cons? |
| 08:22 | rhickey | cemerick: deriving from clojure.lang.ASeq will give you cons and much more for free |
| 08:25 | cemerick | rhickey: A half-hour ago, I hadn't noticed ASeq :-) |
| 08:26 | cemerick | 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) |
| 08: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 |
| 08:28 | rhickey | cemerick: the sensibility seems, to me, to be in the eyes of the conser, not the consee |
| 08:29 | cemerick | rhickey: True enough. That's sometimes hard to see when one is playing both sides of the fence. |
| 08:29 | rhickey | :) |
| 08:48 | cemerick | This might be unreasonable given the current impl, but would be nice in some circumstances to have full destructuring available in def. |
| 08:48 | cemerick | s/would/it would |
| 08:48 | rhickey | in order to def more than one thing at a time? |
| 08: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 :-) ). |
| 08:58 | cemerick | It's an infrequent pattern, of course, so it may not be worth thinking about too much. |
| 09:01 | rhickey | destructuring is available a la carte: |
| 09:01 | rhickey | user=> (destructure '[[a b] x]) |
| 09:01 | rhickey | [vec__2149 x a (clojure/nth vec__2149 0 nil) b (clojure/nth vec__2149 1 nil)] |
| 09:01 | rhickey | user=> (destructure '[{:keys [a b]} x]) |
| 09:01 | rhickey | [map__2150 x a (clojure/get map__2150 :a) b (clojure/get map__2150 :b)] |
| 09:06 | cemerick | Very nice. |
| 09:06 | cemerick | That's not in the docs anywhere, though -- I guess only defns that have docstrings make it in. |
| 09: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. |
| 09: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 |
| 09:09 | cemerick | rhickey: Sure, wasn't saying it should be doc'ed. Just happy I didn't pass over it. |
| 09:09 | rhickey | you could easily write a destructuring-def with it |
| 09:10 | rhickey | one trick about it is that it will return its argument if no destructuring was needed |
| 09:11 | cemerick | I might get around to it. The stuff that uses let for destructuring is put to bed at the moment. |
| 09:12 | cemerick | scgilardi: BTW, thanks very much for the lib tweaks (and pred as well...no need to keep carrying around our own similar utils anymore). |
| 09:13 | scgilardi | you're quite welcome. I'm glad you're finding them useful. |
| 09:13 | blackdog | scgilardi, where is this library? |
| 09:14 | blackdog | i don't see one by you in the Files section |
| 09:14 | scgilardi | http://clojure-contrib.svn.sourceforge.net/viewvc/clojure-contrib/ |
| 09:14 | blackdog | ah, didn't know about that |
| 09:14 | blackdog | thx |
| 09:15 | cemerick | Yeah, it took me a minute to look in svn, too. :-) |
| 09:15 | scgilardi | clojure contrib has some cool stuff in it from a few folks :) |
| 09:15 | blackdog | neat, i thought everything of use was on the google group |
| 09:16 | rhickey | I'm hoping to fold some of the great stuff from contribs into Clojure soon after ECOOP next week |
| 09:16 | scgilardi | very cool. have a great trip. are you presenting anything? |
| 09: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 |
| 09:19 | rhickey | 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 |
| 09:19 | rhickey | ? |
| 09:19 | scgilardi | nice (re: presentations). I'll check out the website to see if they make videos or transcripts available. |
| 09: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 |
| 09:26 | scgilardi | yes, it does seem like a light touch with the main goal of sharing the copyright on contributions. Sounds good to me. |
| 09: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. |
| 09:56 | rhickey | It originally got bashed for not having the "Any contribution we |
| 09:56 | rhickey | 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 | Lau_of_DK | Would have been fun to tag-team with the infamous CHOW-zarrrrrrr |
| 11:37 | Lau_of_DK | But I'll let you go |
| 11:37 | Chouser | heh. |
| 11:37 | Chouser | 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 | Chouser | (filter (complement #{:c}) [:a :b :c :d :e]) ==> (:a :b :d :e) |
| 12:17 | Chouser | (filter #(not= % :c) [:a :b :c :d :e]) |
| 12:18 | Chouser | (for [i [:a :b :c :d :e] :when (not= i :c)] i) |
| 12:19 | Chouser | (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 | Chouser | 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 | rhickey | 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 | Chouser | 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: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 | Lau_of_DK | :) |
| 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 | Chouser | 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 | Lau_of_DK | 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 | pjb3 | 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 | Chouser | relational |
| 14:05 | pjb3 | You have Servlets, JSPs, access to a database via JDBC, and frameworks built on top of those |
| 14:05 | pjb3 | Chouser: yeah, and the only shared data is in the database |
| 14:06 | pjb3 | I bring this up to discuss the whole "State, you're doing it wrong thing" |
| 14:06 | pjb3 | and I think a valid response to that is |
| 14:06 | pjb3 | "No I'm not, I'm not sharing any data across threads" |
| 14:07 | pjb3 | 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 | pjb3 | the more I like it |
| 14:09 | pjb3 | 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 | pjb3 | rhickey: so that's pretty common in web apps, what's sad about it |
| 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 | rhickey | 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 | rhickey | Chouser: sorry, that was for pjb3 |
| 14:15 | Chouser | ok |
| 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 | Chouser | 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 | rhickey | 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 | rhickey | pjb3: and the easiest way not to share state is to not have it, e.g. use immutable data structures |
| 14:29 | rhickey | 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 | rhickey | same problem - dangling non-memory resource |
| 14:34 | drewr | Chouser: Is that double LET in your CASE macro a common idiom? |
| 14:34 | drewr | (With the GENSYM..) |
| 14:35 | Chouser | rhickey: that's a good point. your weak-ref solution might be the key. |
| 14:35 | Chouser | 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 | Chouser | 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 | rhickey | 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 | Chouser | Hm, apparently doto in boot.clj uses the same idiom for essentially the same reason. |
| 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 | rhickey | plus auto-close on eos |
| 14:50 | rhickey | There isn't a way to let someone off the hook from knowing they're holding a resource |
| 14:51 | rhickey | 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 | rhickey | 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 | Chouser | 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 | pjb3 | 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 | Chouser | but that's not the right direction anyway |
| 15:05 | Chouser | 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 | Chouser | 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 | rhickey | 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 | Chouser | 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 | Chouser | 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 | Chouser | 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 | Chouser | 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 | cemerick | 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 | abrooks | rhickey: I was going to bring up a related topic the other day when I was mentioning remote concurrency. |
| 17:52 | abrooks | 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 | abrooks | The proxying object would be application and object type specific to suit different performance / overhead tradeoffs. |
| 17:56 | abrooks | 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 | abrooks | 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 | abrooks | 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 | abrooks | 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 | pjb3 | 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 | pjb3 | 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 | pjb3 | unable to resolve gen-and-save-class |
| 19:07 | pjb3 | that's progress |
| 19:07 | pjb3 | 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 | jgrant | or some way to package everything up in a jar ? |
| 19:09 | rhickey | not if that does what I think it does |
| 19:10 | rhickey | Clojure does no ahead-of-time compilation at this point |
| 19:10 | rhickey | and serializing the state of Java is not going to happen |
| 19:11 | jgrant | yea i can see why |
| 19:11 | jgrant | 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 | jgrant | 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 | rhickey | user.clj will be found on the classpath |
| 19:37 | jgrant | that's what i gathered from read loadResourceScript |
| 19:38 | jgrant | 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 | jgrant | this works ... |
| 19:47 | jgrant | java -cp user.jar:clojure.jar clojure.lang.Script |
| 19:49 | jgrant | 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 | jgrant | (reduce (fn [x y] (conj x y)) '(0) '(1 2 3 4 5) ) |
| 20:06 | jgrant | (i guess that's one possible definition of collect for clojure) |
| 20:26 | jgrant | 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 | pjb3 | (rem 5 2 ) |
| 20:27 | jgrant | thx |
| 20:27 | jgrant | and yea |
| 20:43 | jgrant | rhickey : only one problem with this --> java -cp ../user.jar:../clojure.jar clojure.lang.Script -- hello |
| 20:43 | jgrant | *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 | slava | 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 | rhickey | 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: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 | slava | 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 | slava | 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 | jgrant | 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 | jgrant | 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 | jgrant | 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 | jgrant | 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 | slava | 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 | Chouser | s/to us/to use/ |
| 22:46 | Chouser | 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 | Chouser | 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 | Chouser | 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 | rhickey | 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 | rhickey | 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 | Chouser | ok, see ya |
| 23:24 | Chouser | does anyone know if bopping in and out of try blocks is expensive? |
| 23:27 | Chouser | as in, is it much worse to put the try block inside a loop rather than outside? |