#clojure log - Sep 10 2008

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

7:49 rhickey: Chouser: js persistent vector is neat!

8:59 Chouser: I was surprised at how much of the code ended up almost identical to the Java.

9:28 rhickey: oh, I didn't notice you weren't here.

9:29 I was surprised at how much of PersistentVector.js ended up almost identical to the Java.

9:29 rhickey: right

9:29 that's good

9:29 Chouser: I'll have to do some timing tests to make sure using a closure structure like that isn't too slow

9:30 I'm also not sure about trying to mimic the Java inheritence heirarchy.

9:30 rhickey: slow vs what? what's the alternative?

9:31 Chouser: using prototypes, which is the "normal" way to do "classes" in JavaScript.

9:31 rhickey: why didn't you use prototypes?

9:32 Chouser: they expose all object data as public mutable fields -- nothing private, no protection from assignment

9:33 Last time I looked into performance, closures were slightly slower to create, but slightly faster for making method calls. But JS engines have changed since then.

9:34 rhickey: Yeah, I have a feeling you're not going to get the perf from V8-like things without prototypes

9:35 aking:

9:36 Chouser: ok, we'll see. The textual difference in the .js isn't very big, so it'll be easy enough to try some different arrangements.

9:36 rhickey: I wouldn't worry about access - JS is kind of a free for all anyway. Accident vs malice...

9:37 Chouser: hm.

9:37 rhickey: but there is a certain elegance to the closures for sure

10:05 StartsWithK: to use genclass with ns, do i create /package/subpack/Class/Class.clj or /package/subpack/Class.clj

10:05 and inside it do i deklare (ns mypack.Class) or (ns mypack) and write functions like (defn init[this] ..) or (defn Class-init [this] ..)

10:09 Chouser: /package/subpack/Class.clj

10:10 (ns package.subpack)

10:10 StartsWithK: and (ns package.subpack) with (defn Class-init[this]) ?

10:10 Chouser: (defn Class-init ...)

10:10 right, except init doesn't get "this"

10:11 StartsWithK: wait, init is constructor?

10:11 what is 'init' method then

10:13 Chouser: it gets called at object construction time with the args given to the constructor call

10:13 Must return [ [superclass-constructor-args] state]

10:23 StartsWithK: and, how will i implement real init method?

10:23 sorry, maybe i didn't understand this (defn Class [..] ..) is constructor, or (defn Class-init ..)

10:24 Chouser: don't do (defn Class ...). Use (defn Class-init ...) to define what should happen when your object is constructed.

10:25 StartsWithK: hmm..

10:26 what should i do about applets init method then?

10:26 cemerick: StartsWithK: you can name the "constructor" function anything you want in the gen-class spec

10:26 :init 'my-init-fn

10:27 Chouser: ...and then (defn Class-my-init-fn ...)

10:34 StartsWithK: oh i see

10:34 thanks

11:35 drewr: Oh wow. I love how merging a map into a sorted map keeps the sorted map.

11:41 cemerick: The fact that the generated API docs don't filter back into the topical pages (Data Structures, Sequences, etc) is unfortunate

11:49 Chouser: I was thinking it might be useful to tag functions with related keywords (types they operate on plus some other categories) and then have a page per tag

11:50 that way if you have a vector and want to know what you can do with it, you'd have some place to look that would be up-to-date

11:50 rhickey_: Chouser: just hopped on - context?

11:50 Chouser: This was one of my gripes about CL -- finding the one function you need out of the hundreds available was daunting.

11:50 rhickey_: Chouser: did you use apropos?

11:51 Chouser: rhickey_: cemerick just noted the topical pages don't get updates from the generated API docs.

11:51 rhickey_: I don't think so.

11:51 rhickey_: Chouser: right, and moving forward I;d like the topical pages to be more prose and less reference, letting the latter fall to API page

11:52 Chouser: I agree with that, except for the whole it leaves in getting from an idea to the existing function that implements it.

11:52 s/whole/hole/

11:52 cemerick: apropos never worked for me (not that I was in CL-land very long) -- i.e. (apropos "map") in clojure wouldn't list assoc, etc

11:53 Chouser's notion of tagging fns sounds very appealing, at first blush.

11:54 rhickey_: Chouser: but see the (newer) doc for sets, which contain links to API sections

11:55 cemerick: but (find-doc "map") does

11:56 cemerick: rhickey_ has a magic ability to inject into my running clojure repl exactly the functions I'm looking for! That's what I call remote code loading. :-P

11:57 rhickey_: cemerick: tagging is like semantic web - manual extra work, find-doc and things like it are like google - automatic, based on work already being done

11:57 cemerick: For me, an ideal reference would be the prose-oriented topical sections, with some abbreviated output from find-doc appended to each section

11:58 Chouser: gah, I've still got a bug in PersistentVector.js. Debugging this might me easier if I had a clue what it's doing. ;-)

11:58 rhickey_: one problem is the huge overlap in the abstractions - so many functions can be used on almost anything

12:00 Chouser: 1000 items work fine. above 10000 something's broken.

12:00 rhickey_: cemerick: see the section on sets here: http://clojure.org/data_structures, lots of links in prose

12:01 cemerick: rhickey_: yeah, I saw -- but those links fall into that manual extra work category, so the new super-nifty fn related to sets won't be noted there until you decide to revisit the prose

12:02 rhickey_: cemerick: well, the prose is going to exist anyway. Maybe a browser plugin that, given a highlighted word, went to API#theword ?

12:03 cemerick: hrm, greasemonkey to the rescue

12:03 rhickey_: cemerick: but yes, for new stuff its find-doc

12:03 Chouser: (find-doc "set") is pretty noisy

12:04 cemerick: Chouser: moving a search like that out of the repl will do wonders; I think I have my next 2-hour side project :-)

12:29 I need to read the docs more often. I didn't realize that named anonymous fns were available until 5 min ago.

12:39 shoover: cemerick: what are you doing with greasemonkey?

12:41 cemerick: shoover: nothing at the moment. We use it for a couple of ad-hoc integrations between internal systems here. I have an idea to use it to build an easy/fast clojure API lookup tool.

12:43 pjstadig: ok

12:43 i made a .deb of clojure

12:44 it wasn't as hard as i expected

12:44 Chouser: pjstadig: great!

12:44 pjstadig: i used the bin scripts from http://github.com/jochu/clojure-extra/tree/master

12:45 i'm extremely newb at this though, so i'm not sure what to do next

12:45 i was thinking of setting up a personal package archive on launchpad.net

12:46 and i guess maybe the debian build infrastructure should be merged back into the clojure source?

12:46 or I guess i could maintain it separately

12:47 kotarak: Is there a way to delegate method calls of an interface to a specific component? (More a Java question....)

12:54 Chouser: pjstadig: I'm not sure either -- can you submit it to the debian project itself?

12:55 kotarak: what do you mean by component?

12:55 pjstadig: to get clojure included in debian i, or someone, would need to become a debian developer and the official maintainer of the package

12:56 it would also be fine (i think...for now) to just build a .deb along with a .zip and distribute them on sf.net or in whatever way people can download clojure

12:57 kotarak: say I have: class A implements IFoo { AFoo f /* <- implements IFoo */; delegate IFoo to f /* ?? Possible? Instead defining all IFoo functions wrappers. */; void someIFooFunc() { return f.someIFooFunc(); } /* <- very tedious and boring */ }

12:58 Chouser: ahhh... hm.

12:58 I imagine you could cook up a macro to generate a proxy form that would do that.

12:59 kotarak: something like snit for Tcl would be nice.

12:59 Chouser: kotarak: ever written a macro? they're fun

13:00 kotarak: chouser: have written lot's of macros. They are fun. :)

13:00 Chouser: the problem is that it's pretty rare to run into a problem where a macro is the right solution.

13:01 But I think you found one. If you don't write it, I just might.

13:01 kotarak: Let me try.

13:01 I will have a look and some inspirations from snit.

13:02 It's pretty nice in this respect. (It's actually a OOP system for Tcl, which does not have inheritance but only delegation)

13:02 Chouser: huh.

13:07 kotarak: What's the typical OOP example? class Human { method eat() { hungry = false }; lots of other stuff... }; class MaleHuman { method eat() { super(); say "Buuurp" } }

13:07 achim_p: rhickey_: what about a bit of markup for clojure doc strings to avoid the tagging extra work? it had to be very lightweight though ...

13:08 people writing docs could add hints about terms refering to clojure types or functions, something like: "Returns a :map: that consists of the rest of the :map:s |conj|-ed onto the first."

13:09 kotarak: With snit this looks like: class Human (the same)...; class MaleHuman { component Human h; delegate * to h; method eat() { h.eat(); print "Buuurp" } }

13:10 achim_p: maybe something, which is already used? like restructered text or something along the lines...

13:11 rhickey_: achim_p: I'd hate to reduce the readability in the repl

13:14 blackdog: cemerick, is enclojure compiling using clojure head right now?

13:15 oh, that's not really the question, are you using it with the netbeans RC

13:35 Chouser: rhickey_: PersistentVector.root shouldn't get longer than 32?

13:35 cemerick: blackdog: I haven't built enclojure in a while; we're using it in conjunction with clojure r1006, I believe.

13:36 blackdog: ok, thanks, i had troubles with nb6.5 and decided to leave it

13:37 cemerick: I'm using it with 6.5 right now -- it required a small patch so as to not break all debugging (including java debugging)

13:37 blackdog: ah, that's what i ran into then

13:38 i didn't have the gumption to investigate

13:38 cemerick: blackdog: here's the discussion; I describe the patch we're using right now at the end of my message: http://groups.google.com/group/enclojure/browse_thread/thread/b17883c64f80c2af

13:38 blackdog: ta, coolio, I'll give it a shot once the latest downloads

13:48 achim_p: kotarak: restructured text looks nice (at first glance), i.e. very much like plain text. i didn't intend to propose using || and ::, they were merely examples of what i meant by lightweight.

13:50 rhickey_: yes, repl readibility would be a problem. print-doc could be changed to cull the markup, of course. tool support could benefit from doc markup altogether (editors with highlighting, cross references in doc browsers etc.)

13:50 but i certainly understand your concerns

13:51 kotarak: achim_p: no offence intended. But before one invents new formats, one should check what's already there. restructered text, markdown, etc... I use NaturalDocs to extract the docs from the sources. That provides indexes etc. w/o disturbing the REPL readability too much.

13:56 rhickey_: Chouser: no, no node should ever get longer than 32, it's a 32-way tree, 5 bits per level

13:56 achim_p: as long as it's not javadoc/html, i'm fine with it ;-)

13:57 kotarak: achim_p: yeah, javadoc is not the best choice....

13:59 rhickey_: kotarak: do you have a clojure config file for NaturalDocs?

13:59 Chouser: rhickey_: ok, thanks. I think my problem is when the tree depth goes to 3

14:00 hoeck_: rhickey_: have you looked at print.clj?

14:01 rhickey_: hoeck_: yes, will incorporate soon, thanks! Looking to get a release out and may not change anything but bugs before then

14:03 kotarak: rhickey_: Well...., I have to work around some issues with the docstrings. I don't want to duplicate the docs. So I decided to use | as additional "comment". I can live with |, but it's not perfect of course.

14:03 lisppaste8: kotarak pasted "docstring with naturaldocs" at http://paste.lisp.org/display/66606

14:04 kotarak: But I like the way it looks in the source. Although it's pretty verbose. I don't know. That's the price for something like nd or robodoc, I guess.

14:05 rhickey_: kotarak: so what does NaturalDocs do for you?

14:05 hoeck_: rhickey_: aha, ok, thanks too, learned a lot about *warn-on-reflection* and multimethods

14:06 rhickey_: hoeck_: although it would be nice to have in as a practical example of multimethods

14:07 kotarak: rhickey_: it recognises the foo is a function belonging to a namespace. It uses this information to create a set of html files with indexes for namespace, functions, structs, whatever. One can easily link to a function (<foo>), even to another namespace (<other.namespace.foo>) (Note: last ., not / another limitation, I guess).

14:09 hoeck_: rhickey_: so will you keep the original RT.print()?

14:09 kotarak: One could probably write a Perl module for full support. But to be honest: my Perl is too rusty and I'd rather spend my time with Clojure instead of Perl...

14:11 rhickey_: hoeck_: at the end of the day, no

15:23 kotarak: In case I have a jar with some .clj inside and a running REPL. When I update the jar, is this available in the Repl? Or do I have to restart?

15:40 cemerick: kotarak: if the updates are to .clj files, then you just need to re-load those files; if you update already-loaded classfiles, then you have to restart the jvm

15:40 kotarak: cemerick: That's ok. Thanks.

15:41 cemerick: There's ways around that with subordinate classloaders and such, but if you need generalized code reloading, then you're better off using a framework that already supports that (OSGI, etc) (although I don't know what the status is on clojure/osgi compatibility)

15:42 Chouser: using the (new) load doesn't seem to run the new .clj from an updated .jar

15:42 kotarak: -.-

15:43 cemerick: Doesn't lib have a :reload flag or somesuch?

15:43 kotarak: It's more about the jar being recognised, I think. (At least I would suspect this.)

15:43 cemerick: So, I have an interface that defines two overloads of a method, both taking one argument (of different types). Is there a way to pair this up with a gen-class implementation?

15:44 Chouser: I've got a .jar in my classpath with t2.clj inside. I can use (load "/t2.clj") to load it.

15:45 rhickey_: cemerick: yes, you can distinguish method implementations by name, just append the types MyClass-myMethod-X MyClass-myMethod-Y

15:45 Chouser: If I then change the .jar, and re-run (load "/t2.clj"), it doesn't seem to get the new changes.

15:47 cemerick: rhickey_: OK, I'll give that a try; just out of curiosity, will that work with init fns as well?

15:48 rhickey_: cemerick: no, one ctor

15:49 cemerick: hold on...

15:51 cemerick: rhickey_: OK, thanks. FWIW, that'd be very nice to have -- I often have two constructors for a genclass: one that takes some initialization value, and another that takes a PSM that's swapped in as the state of the new instance when "mutating" it

15:52 I end up adding a dummy Object argument to the latter to distinguish the arity...

15:54 rhickey_: cemerick: if same arity will be routed to same fn, then you can switch on type

15:56 cemerick: rhickey_: Yeah, I suppose. Having the extra dummy argument is cleaner IMO, by just a hair (especially since only clojure code calls it).

16:27 StartsWithK: what am i doing wring error: http://pastebin.com/d4834a728 genclass: http://pastebin.com/d6bb3915f client: http://pastebin.com/m45f76093

16:28 it was all working with old genclass, i don't know what revision i was using before of clojure, but with trunk i can't make it work anymore

16:35 Chouser: it looks like maybe your gen'ed .class files are out of date

16:36 you might try deleting them and re-running the gen-and-save-class

17:19 wow, using prototypes intead of closures speeds up V8 by around 25%

17:20 rhickey_: hmm

17:21 Chouser: oops, I mean to about 25% of the CPU time. 75% improvment.

17:21 rhickey_: ok, wow

17:21 Chouser: rhino only gets a 14% bump.

17:22 abrooks: Chouser: Rhino??? Clojure in JavaScript in Java on the JVM? Nooo!

17:22 pjstadig: haha

17:22 * Chouser giggles

17:27 Chouser: In V8, reads of a raw array are only 40% faster than reads of PV

17:28 rhickey_: cool

17:28 Chouser: writes to PV are 36 to 61 times slower than the raw array.

17:28 rhickey_: ouch

17:30 Chouser: but that's because V8 is doing something really impressive with the raw array. On Rhino, writes are only 10 to 25 times slower.

17:30 dinnertime

17:30 rhickey_: append is more important than write at index

Logging service provided by n01se.net