#clojure log - Sep 11 2008

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

7:47 StartsWithK: i was just reading results of latest poll

7:47 one of the thing metioned was cpan like repository

7:47 that sounds like realy good idea

7:47 so, to share how i started to build my own app

7:48 first i was using ant, but that didn't work that great, no dependancies to extrenal jar.. i had to download them all to lib/ and sync them manualy

7:49 then i moved for short time to buildr (ruby make like system for java, part of apache incubator)

7:49 it supports maven repositories, so that worked great

7:49 but you have to install ruby/jruby and buildr, and that could be a pain for most users

7:50 so now i am at ant+ivy, ivy is dependancy tracker (part of apache)

7:51 why i like it is, it just resolves dependanicies, it supports its own repository format, maven repositories, or general urlresolvers

7:51 also, there is no need to install ivy manualy, it can be done from ant build

7:52 only thing missing at the moment is maven/ivy repository with clojure and clojure-contrib, then you wouldn't need to distribute clojure.jar with your own lib

7:54 cemerick: Yeah, we use ant+ivy as well. Although, we only use our own internal repo, and we'll always distribute a "full stack", with all dependencies included.

8:00 StartsWithK: i think ivy would be a good choice

8:01 maven looks to much java orientated, and that didn't fit that well for genclass and similar thing for me

10:32 achim_p: hi! is there an easy way of turning a java.util.Enumeration object into a (lazy) seq?

10:33 rhickey_: achim_p: enumeration-seq

10:34 (find-doc "Enumeration") finds it

10:36 achim_p: oh, embarrassing ;-) thanks for the pointer!

10:36 leafw: rhickey_: I really like the 'new' way of calling static methods and fields. You have finally captured what they really are: unbound functions within a namespace. Calling them like other clojure namespaces, with '/', is just brilliant.

10:37 it's easier to explain to a novice that a static method is by using clojure, than by using java itself.

10:37 s/that/what/

10:38 rhickey_: leafw: just need to get everyone to transition to the new style...

10:38 leafw: I will update my wikis.

10:47 it's done/

10:56 Chouser: rhickey_: were you serious about gen'ing JS just like AOT JVM bytecode? Or would macroexpand still be a useful approach.

10:57 rhickey_: AOT Java/JavaScript _source_

10:57 Chouser: oh, Java source?

10:58 rhickey_: Right, like I used to do. But that is less compelling than JS

10:59 blackdog_: that sounds really good to me, finally client and server code in one decent language :)

10:59 Chouser: naw, there are lots of people who want AOT Java. They'd probably be content with Java source.

10:59 rhickey_: as I said before, AOT Java for what purpose? For startup speed, I have ideas that won't require AOT

11:00 Chouser: anyway, my real question is how you'd recommend doing the macroexpand of interior expressions, assuming macroexpand is a useful approach.

11:01 rhickey_: the idea is cal Compiler.analyze as done now - that does all of the heavy lifting. Then just to emitJS per expression type

11:01 just do

11:02 blackdog_: and if Chouser has finished the clojure persistent structures by then we're good to go ;)

11:05 Chouser: my goal (dream?) is to get boot.clj auto-gen'ing to JS.

11:06 That will require some stubs/wrappers for a few Java classes. StringBuffer, for example.

11:09 Compiler/analyze is private

11:13 rhickey_: Chouser: so are all of the expression classes, this will require some cooperation from Clojure :)

11:30 Chouser: doesn't analyze do too much? like looking up vars?

11:31 rhickey_: Chouser: I don't know how you compile without resolving names

11:33 Chouser: I was imagining a literal translation from symbols, and then allowing the JS to do resolving.

11:34 rhickey_: what a var becomes in the generated output is still open

11:35 Chouser: (Compiler/analyze Compiler$C/STATEMENT '(def map "test"))

11:36 that throws an exception. Hm, maybe I just need to make sure I'm in the 'clojure namespace like it expects.

12:05 It's also doing static method resolution. I was assuming I'd want host syntax to access JS classes and methods.

15:19 would it be inappropriate for me to put half-baked non-functional peices of clojurescript into the clojure-contrib repo?

15:19 or even pieces?

15:23 rhickey_: Chouser: sure, go ahead - have to start somewhere!

15:26 Chouser: well, I just didn't know if clojure-contrib was the right place to dump it.

15:27 Don't want to scare the newbies. ;-)

15:27 rhickey_: People pick and choose from contrib right? Not one bundle?

15:28 Chouser: I dunno about other, but I "svn up" the whole thing, and use (ns (:require ...)) to pick out what I want to use.

15:28 s/other/other people/

15:29 rhickey_: Ok, well, just put work-in-progess comments in there. I don't think we need another project

15:31 Chouser: ok

15:35 cemerick: fwiw, we bundle all of clojure.contrib into our jars. I suppose it's only a matter of time before we need to establish exactly what we use and what we don't.

15:36 it certainly seems silly to have separate projects at this point

15:36 rhickey_: cemerick: trusting souls :)

15:37 cemerick: rhickey_: I've been standing on the shoulders of giants forever; I'd be fiddling with microcode if I didn't trust others implicitly. :-)

15:38 Chouser: I'll put it in src/clojurescript, so if you're bundling src/clojure/contrib you're already set to skip this stuff.

15:39 or maybe I'll put it in clojurescript right at the top level (instead of in src)

15:42 cemerick: wow, defvar and friends put the docstring *last*

15:42 StartsWithK_: maybe you could create your own branch?

15:47 rhickey_: no branches please

15:50 abrooks: Branching in Subversion is just as convenient as maintaining another family on the side. I recommend against it.

15:51 rhickey_: I've been thinking of writing up a plan to use Mercurial (or git) for Clojure. Is that a waste of time or something that would be helpful.

15:51 rhickey_: abrooks: for me to use mercurial?

15:51 abrooks: Well, yes, you would be part of that. :)

15:53 rhickey_: I don't think so. there's nothing wrong with the SVN at present, and those that want to see it via git can

15:53 abrooks: We get the most benefit when the main repo (rather than just a mirror) is Mercurial.

15:53 rhickey_: how so?

15:54 abrooks: Right now we have a single, linear history. If people are tracking changes on the side, rebasing and other activities are a lot more annoying. Particularly if some of their changes are accepted upstream and some aren't.

15:54 Part of the writup would be a rationale of why it would be beneficial.

15:55 Chouser: abrooks: you'll be fighting a relative derth of IDE integration, compared to svn.

15:56 abrooks: When I say Mercurial, I also mean git. I think either would be fine (having used both) though I think Mercurial is sufficiently easier for Clojure's usage.

15:56 rhickey_: abrooks: feel free to write it up, but I am strongly inclined to stick with large hosts like SF or Google code, and I care about IDE support

15:56 abrooks: Chouser: tortiose-hg is out there.

15:56 I'll be most inclined to spend the time if I think the chances are good.

15:57 StartsWithK_: netbeans also has mercurial support now

15:57 abrooks: IDE/GUI tools -- noted. That's not something I generally care about but I think the state of the world is good. I'll have to check in detail.

16:02 cemerick: Are any super-automagic yet reliable ways to have a svn repo mirror a git repo? If clojure goes to git/hg (and yes, I know rhickey_'s not super-interested, but still), I'll need to put together something to keep me in the sane (for me) world of svn.

16:07 abrooks: Providing a flat svn mirror of git/hg is not a problem -- you just lose some information that Subversion has no way of storing.

16:07 Tailor works quite well from what I hear: http://progetti.arstecnica.it/tailor

16:07 You just want to keep the svn changes flowing out from git or flowing into git. Bi-directional sync gets nasty.

16:31 Chouser: bi-directional sync with git when the canonical repo is svn is not a problem.

16:35 abrooks: True but I think that's an odd way to do things. Can you properly publish a git-svn repo? I've not tried.

16:35 arohner: it's pretty straight forward as long as your git history isn't too complicated

16:35 abrooks: Well, you're still missing out on all the merge history from the canonical svn repo, anyways.

16:35 arohner: when using git-svn, bidirectional works well both ways. just treat git like svn

16:35 :-)

16:36 the svn merge history is represented in git too, IIRC

16:37 abrooks: arohner: But manual merges done on the Subversion side of things aren't shown with merge history (at least for Subversion 1.4). They're just ugly checkins.

16:39 arohner: huh. I either haven't run into that, or haven't noticed

16:39 I do know that complicated merges on the git side before going into svn are messy

19:55 Chouser: clojurescript macros get expanded by the JVM

19:55 ozzilee: So, today I notice that the half-assed site I put up ages ago is the number one google result for "scheme clojure". Apparently the scheme people aren't too interested in clojure :-)

19:56 rhickey: Chouser: is that a question? (just arrived)

19:57 Chouser: macros can call any functions defined so far, which means all functions must be defined in the JVM, doesn't it?

19:57 but of course some functions are going to refer to JavaScript objects, so those function will fail to compile on the JVM

20:01 rhickey: no, the only functions that run at compile time are the ones needed to _expand_ the macro, not the ones it expands into. The former are likely to already exist in Clojure

20:02 parenscript works the same way - macros are written in and run in CL, but expand into JS

20:04 Chouser: I'm trying to process boot.clj, but of course it defines functions and then defines macros that use them.

20:04 rhickey: process boot.clj how?

20:05 Chouser: running each top-level form through Compiler/analyze and then translating the results into JavaScript.

20:07 for now I'm eval'ing each in a 'tmp namespace as well as translating to JavaScript. That should work for all of boot.clj.

20:08 I guess for user-provided forms I'll rely on the user deciding which will be for the JVM and which will be run through formtojs.

20:09 rhickey: I'm not sure what your objective is. I;d shoot for having a fully-loaded Clojure 'compile' a file to JS on demand. It's not at all like the bootstrap of Clojure. I wouldn't expect to have compilation capabilities at all in JS

20:09 that compile could ignore macros

20:11 all you need are emitJS functions for all of the expr types (ok, not all, but that's the essence) If we want to end up with a shareable boot.clj there will need to be more wrapping of Java, so everything goes through RT or something

20:11 Chouser: Here's the kind of expression I'd expect to translate to JS: (let [[a b] foo] (.getElementById document "x"))

20:11 rhickey: no problem

20:13 a simple flag could keep the compiler from trying to resolve types - all calls look reflective and instance

20:13 Chouser: ah, ok, that's one set of problems. That's a flag that doesn't exist, I assume?

20:14 rhickey: yeah, you're not going to be able to glom on a JS compiler without some support :)

20:14 unless you write a full compiler, which would be a lot of work...

20:14 Chouser: oh, clearly. I've already got a giant patch on Compiler.java

20:15 For now all I've had to do is make a bunch of classes public, final fields public, and added some final accessors.

20:15 rhickey: are you adding emitJS methods to the Exprs?

20:16 Chouser: no, I've got a multimethod named tojs

20:16 rhickey: that's fine

20:17 Chouser: Actually, I've got it working through boot.clj up to the first recur.

20:17 rhickey: does JS have the comma operator?

20:17 Chouser: yes

20:18 I haven't needed it yet. I guess that would be a alternate way to do BodyExpr

20:18 rhickey: right, that's good. dropping that from C was a huge mistake for Java/C#, makes using them as compilation targets much harder

20:18 It seem the way to do BodyExpr, no?

20:19 Chouser: it would have been easier: return e1,e2,e3; But I just did: e1;e2;return e3;

20:19 rhickey: You realize by doing this you are going to completely understand Clojure...

20:20 Chouser: except for the Magical STM part :-)

20:20 rhickey: Chouser: what if it's in an expression position?

20:20 you can't say return

20:21 Chouser: yeah, I may need to change BodyExpr. so far it's only been used as the body of what has ended up a JS function.

20:21 but recur's tricky.

20:21 rhickey: you need to pay attention to the context stuff, it deals with the expr/statement dichotomy

20:21 esp. important when generating source

20:22 Chouser: My only thought so far is to put a function in a while loop, and have the function return an array of args to be supplied to the next function call.

20:24 rhickey: no, you emit a function that has the while loop in it, preceded by locals, and it just sets the locals each iteration

20:24 at least JS has closures

20:25 or resets the args

20:26 Chouser: but the args are set in parallel -- the inits for the next iteration all refer to the old values.

20:27 rhickey: use temps

20:27 Chouser: ok

20:29 yeah, I'm using JS closures for let blocks

20:29 rhickey: just have to be careful about JS broken block scope

20:30 Clojure uses stack as temp area for recur

20:31 Chouser: careful about JS broken block scope when choosing temp names?

20:32 rhickey: and local names

20:32 let names

20:38 Chouser: ah, bother. I can't use a JS function for let blocks, because recur needs to pop right past them.

20:39 rhickey: what's wrong with block + locals for let?

20:48 Chouser: JS doesn't give me a new scope for a block, but locals in a let need to be able to shadow any outer scope

20:49 rhickey: shadowing is a compilation detail, just rename

20:49 that's what I was talking about before

20:49 lisppaste8: jamii pasted "cells" at http://paste.lisp.org/display/66688

20:50 jamii pasted "cells java" at http://paste.lisp.org/display/66689

20:52 Chouser: oh, you mean keep track of any names that will be shadowed, store the old values in temps, and restore them after leaving the let?

20:53 rhickey: if the clojure source says x, the JS could say fred (or more likely x1), a nested x would be x2, etc

20:54 so the nested refs target different js locals

20:55 Chouser: oh, I see.

20:55 You can probably guess at this point that I've never written a compiler.

20:56 rhickey: you don't need to track anything, the compiler already 'unique-izes' locals

20:56 Chouser: ok, great.

20:56 rhickey: just give each LocalBinding a unique name

21:09 Chouser: oh, ignore the name field in LocalBinding and make up my own for each?

21:11 rhickey: Chouser: you might want to base it on name for debugging purposes

21:11 but yes, make each unique

21:13 Chouser: I'll need to store that mapping somewhere -- I guess I may need to pass that along as context as I process the tree.

Logging service provided by n01se.net