#clojure log - Sep 15 2008

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

0:14 abrooks: Chouser: That's really nifty! Congrats!

2:11 homercycles: Does anybody know if a book is currently being written about clojure? I've read the first 8 chapters of Practical Common Lisp to starting "thinking lisp" but want to start doing something with clojure, but am not sure where to get started really

2:12 online reference is nice but probably not covered to the level I'll need in order to understand

2:13 clojure.org/reader - especially the stuff on dispatch - needs more explaining for people like me :-)

11:55 Chouser: rhickey_: is there any easy way to determine if a FnMethod is going to be used as a target for a recur?

12:22 rhickey_: Chouser: doesn't appear so

12:24 Chouser: ok. I'm putting a do{}while in every function just in case. Not the end of the world, but I was hoping to skip that if not needed.

12:24 rhickey_: yuck

12:25 Chouser: Doesn't seem worth walking the tree differentiating between enclosed fns and loops vs. everything else.

12:29 rhickey_: you walk the tree when you emit anyway, just track the nesting level. If you look at the compiler, you'll see it tracks loop targets during emit, not analyze. Look for the use of LOOP_LABEL. You could track the (potential) loop target similarly with a dynamic var

12:30 each fn and loop pushes on the stack, when you hit a recur, top of stack is target. If you don't recur, stack is not used but at least the generated code isn't polluted

12:32 Chouser: hm. so far I've ignored subtrees when emitting the current level.

12:32 I've passed context down, but not tried to return anything except the code to be emitted.

12:33 rhickey_: I see, yeah in bytecode I just drop labels as I go...

12:34 still, possible to do cleanly with mutable dynamic vars

12:35 Chouser: oh, yeah I hadn't considered that approach. not exactly immaculate, but if you're will to call it clean I guess I'll give it a shot.

12:36 rhickey_: it's thread safe, and stack based. The compiler does similar things...

12:37 Chouser: biab

13:07 That's the first time I've explicitly used the stack built into a dynamic var. Not too shabby.

13:07 rhickey_: not too

13:08 it's sort of made for this problem

13:08 communicating across nested scopes

13:14 Chouser: Well it tightens up the .js pretty well. The only bit of cruft I've still got is a local var declared for functions even when nothing internal ever refers to it.

13:20 lisppaste8: Chouser pasted "JavaScript emitted by tojs" at http://paste.lisp.org/display/66866

13:22 rhickey_: cool

13:30 Chouser: I sometimes get a NPE from getAndIncLocalNum when the outermost form I'm analyzing isn't a def or a fn.

13:31 Like this, for example: (doseq src (script-src) (prn src))

13:31 Is there something better I can do than wrapping it in ((fn [] ...)) like I am now?

13:33 rhickey_: no, that's the right thing, else you will be writing an interpreter too. (see all the evals in addition to the emits in the Expr classes?)

13:41 added lazy parallel pmap (in rev 1026)

13:57 Chouser: I did see those evals, but I didn't pretend to understand them.

14:18 more features less code! (re: pmap)

14:51 arohner: rhickey_: did you see my compiler error patch?

14:52 Chouser: arohner: I know very little about Java exceptions. Does your patch end up converting exceptions of all types to Exception instances?

14:53 arohner: oh, that's a good point

14:53 it doesn't convert the thrown exception, but it does wrap it in an Exception

14:53 but that shouldn't change the semantics of trying to catch exceptions

14:54 Chouser: oh, you can still catch the more specific exception type inside?

14:54 arohner: no, but compiler.java isn't picky about the types of exceptions it throws

14:54 so, I *think* I'm not making the situation any worse, but I'm not making it better

14:55 wrt to catching exceptions

14:55 I guess I need to clarify that. because java's checked exceptions, you have to declare what type of exceptions you throw

14:56 right now, compiler.java does very little of that, and just declares it throws Exception

14:57 we could change things so that for example Compiler.load() throws a clojure.lang.loadFile exception, etc

14:57 but that doesn't really buy you much

14:58 It looks like rhickey is writing C in java. I don't blame him, that's probably what I would do.

14:58 Chouser: I'm not really qualified to have an opinion. Just sniping. :-)

14:58 arohner: I'm not entirely sure I am either :-)

15:01 rhickey_: arohner: C in Java? in what way?

15:02 arohner: indentation :-) I know you're using inheritance, OO in some places. I don't know, just a feeling I got

15:03 it didn't look like "standard" java

15:03 not that there's anything wrong with that

15:05 rhickey_: It's certainly not C-like

15:07 Chouser: heh

15:07 arohner: that may not have been the fastest path to getting your patch accepted. ;-)

15:07 arohner: hah

15:07 rhickey_: http://n01se.net/paste/HTx

15:08 arohner: pretty

15:09 rhickey_: I'm really not trying to insult you. The code is nice. It didn't look like standard java, and when I tried to figure out what it looked like, the first thing that popped into my head was "C". I know that's not entirely correct.

15:10 rhickey_: but I think it's an interesting question - in what ways does it differ from 'standard Java'? (and I agree it is different) It's not C-like, so you need a better answer

15:10 answer/snipe :)

15:11 arohner: you're not constructing hammer factories, for one

15:11 http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12

15:12 ozzilee: The indentation's all fucked up, for another :-)

15:12 I spent about half an hour trying to get Eclipse to match the indentation... no dice.

15:13 arohner: maybe it's the fact that 90% of the compiler code is pure code. Most java I've seen is just gluing one library to another

15:15 several of the important classes are arranged as OO for organization rather than functionality

15:15 rhickey_: The compiler code is especially different in that it uses the Clojure persistent data structures, not as pretty in Java, and uses Clojure's dynamic vars too.

15:15 arohner: like what?

15:15 arohner: i.e. Compiler.java. lots of static functions, rather than classes with lots of internal state

15:16 which of course fits clojure's style

15:18 rhickey_: ozzilee: switch to IntelliJ

15:19 ozzilee: rhickey_: Ok, I'll try that next time I load it up.

15:21 Chouser: arohner: nice link. Definitely the feeling I get from Java.

15:31 rhickey_: In this code I'm writing, having an :interpose for "for" would be awfully handy. Thoughts?

15:32 rhickey_: I think you need to explain that to me

15:34 Chouser: (interpose 0 (for [i (range 3)] i))

15:34 (for [i (range 3) :interpose 0] i))

15:34 rhickey_: they seem to be the same length

15:34 Chouser: Hm, it's not terribly compelling when written like that is it.

15:36 When the "for" is multi-line, having interpose at the front forces "for" to be much more deeply nested than in the latter case.

15:37 ozzilee: Chouser: You mean there's a lot of blank space to the left of every line in the body of the for?

15:37 parth_m: rhickey: I have been toying with the idea of creating a user friendly clojure shell for the past few days (with jline integration, history, and stuff). Hopefully something like what ipython does for core python. Wanted your opinion on the same. Initial proto is here: http://code.google.com/p/iclj/source/browse/trunk/iclj.clj

15:37 ozzilee: Chouser: Hmm nm.

15:37 lisppaste8: Chouser pasted "proposed :interpose" at http://paste.lisp.org/display/66878

15:38 parth_m: Being in clj its easy to enhance and modify.

15:38 lisppaste8: parth_m pasted "interaction" at http://paste.lisp.org/display/66879

15:38 Chouser: ozzilee: yeah, you're right.

15:38 anyway, not a big deal.

15:39 ozzilee: Chouser: Lisp indentation kind of sucks sometimes. I usually just plunk a newline in after the (interpose 0

15:39 parth_m: rhickey: do you say its best to keep something like iclj as a separate project or do you see value in rolling something like this into clojure? Both approaches seem fine to me.

15:40 lisppaste8: rhickey annotated #66878 with "press enter" at http://paste.lisp.org/display/66878#1

15:40 * Chouser shuts up and goes back to coding.

15:42 rhickey_: parth_m: we've been moving along on this line: http://groups.google.com/group/clojure/msg/78ebea4b2719bc7e

15:43 arohner: rhickey_: do you like my patch? is this a good approach? is there anything I should do differently?

15:45 parth_m: Yes. Thats actually nice. But I was thinking that doing the repl in clojure itself may make it easy to maintain and enhance. + there is builtin jline integration (tab-completion and stuff ... i suppose jline works on windows also though I havent tried it).

15:47 rhickey_: parth_m: yes, repls are trivial to write. jline is a dep I don't want to get into

15:50 arohner: It seems more like a band-aid than substantive. Given the abbreviated stack trace (see above), the real target should be at the exception generation points themselves, where I have enough info to talk about the nature of the problem

15:50 arohner: where is the abbreviated stack trace?

15:51 rhickey_: http://groups.google.com/group/clojure/msg/78ebea4b2719bc7e

15:51 but I'm not putting any of this in until after I cut a release

15:52 ozzilee: parth_m: I think a separate project for that would be cool. I can think of some repl features that would be cool to see, but probably would get implemented very quickly in the main clojure repo.

15:52 *probably wouldn't

15:54 parth_m: rhickey: jline seems fairly common now (as its under BSD license). groovysh and jruby are using it. Is the intent to keep the distribution small? The problem with using jline from the command line is that we don't get tab-completion. And rlwrap is unix only.

15:54 arohner: rhickey_: it is superficial, but it does help. you have different information at the exception generation point. I wouldn't say it's more

15:55 for example, load a.clj, a.clj requires b.clj. b.clj generates an exception. print the sourcePath at that point, and it will say a.clj

15:55 rhickey_: jline is not pure Java on windows. I've seen bug reports on JRuby or Groovy related to jline

15:55 Chouser: There are going to be a bunch of repl projects: intergrated into various editors (emacs, netbeans, jedit, etc.), various terminal wrappers (rlwrap, jline), GUI toolkits (Qt, swing), etc.

15:55 In fact, most of those exist already.

15:56 parth_m: ozzilee: yes. separate project could also work. probably features like color, logging, printing source lines with exception (like ipython) and such. Not sure how much it makes sense to have that in the core REPL.

15:56 arohner: maybe the correct solution is to fix the source path so it correctly points to the file you're actually loading. I can go down that route, but that is exactly the kind of thing I wanted to get buy-on for first.

15:57 parth_m: rhickey: Yes. Thats true.

15:58 Chouser: Yes. That seems to be the standard practice. Especially for lisp :)

15:59 And it has its advantages.

16:00 rhickey_: arohner: doesn't load already set the source path?

16:00 gotta run

16:02 cemerick: I have a genclass impl in a .clj file, which appears to load fine when the corresponding MyClass class is loaded. However, for some baffling reason, a couple of vars that I def using defn are unbound when I refer to them (java.lang.IllegalStateException: Var MyClass-removeAll is unbound, etc). Anyone have any ideas as to why that would be?

16:02 ozzilee: parth_m: I'd like to see a repl brought the up previously typed line with the cursor positioned at the error in the case of one. That would be slick.

16:04 parth_m: ozzilee: I am not sure I understand you.

16:05 Chouser: cemerick: the defn and the exception are in/from the same .clj file?

16:05 ozzilee: parth_m: Sorry, I should have proofread that :-)

16:05 parth_m: :-)

16:06 cemerick: Chouser: No. I bring up a repl with an appropriate classpath, and do (import '(foo.bar MyClass)). Then, foo.bar/MyClass-removeAll => exception.

16:06 ozzilee: parth_m: Say I type "(print foo)", and I get an error saying "Can't find symbol foo". Then instead of a blank line, I'd like to see "(print $foo)", with the $ being the cursor.

16:07 cemerick: Chouser: Oddly, only the functions that start with MyClass-r seem to be affected, although I have to think that that's coincidence.

16:07 Chouser: you're seeing other side-effects from inside the .clj? That's why you're sure it's loading?

16:08 parth_m: ozzilee: Ah. Yes. That would be nice. Getting the line is certainly possible. Don't know about the cursor with jline yet ... still learning jline.

16:08 cemerick: Chouser: Oh, yeah, the .add, .count, .seq, etc., methods all work, and those are implemented in the same .clj file

16:09 parth_m: I suppose I will maintain iclj as a separate project and see how it shapes up. I am hoping to take some inspiration from ipython. Thats a really neat interactive shell.

16:11 cemerick: Chouser: nevermind. An old version of the .clj file was being loaded from another netbeans project I have open. D'oh!

16:11 Chouser: cemerick: yeah, ok. Kinda had to be something like that. ;-)

16:11 * cemerick can't wait until more advanced repl configuration comes to enclojure

16:11 cemerick: yeah, I thought I was in the twilight zone there.

16:12 ozzilee: parth_m: Cool, perhaps I'll make a fork and screw around with adding that feature myself.

16:12 parth_m: Sure.

17:40 drewr: Is there an example in the wild of when fnseq would be used? I cannot come up with a case for it by perusing the source.

17:42 rhickey: drewr: it used to be used in lazy-cons, now it's legacy

17:42 drewr: Ah, OK.

Logging service provided by n01se.net