#clojure log - May 23 2008

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

0:53 drewr: When I say (proxy [some.package.Foo]), what is it that I get back? Is it a derived anonymous class inherited from Foo that I can then instantiate?

8:19 asbjxrn: Any plans for when the next release will be?

8:21 rhickey: I was hoping for some more feedback about the most recent additions - genclass and parallel, and for any final feedback on the Java syntax sugar. I could do a release soon.

8:21 There's also a very hot math/inlining optimization I'm working on that I might try to squeeze in

8:22 cgrand: wow

8:23 rhickey: Made naive fib 4x as fast

8:23 cgrand: inlined but still boxed I presume

8:24 rhickey: Boxed across call boundaries. The cool thing is the inlining is done by HotSpot, if the code path looks right

8:25 so the inlining on my part is just to typed method calls, no primitive op support in code gen

8:29 asbjxrn: Can't give you much feedback, I'm afraid. The little time I do get to spend on clojure is mostly spent fumbling around...

8:58 blackdog: newbie alert, how do i get command line arguments?

8:59 rhickey: *command-line-args*

8:59 blackdog: ah, thanks

10:20 drewr: Regarding *command-line-args*, how do you pass program arguments through the JVM invocation?

10:20 rhickey: at the end

10:21 drewr: The java binary thinks it's an argument for him.

10:21 Like, another source file.

10:21 $ java -cp ~/tmp/src/clojure/clojure.jar clojure.lang.Script cmdline.clj foo bar

10:21 java.io.FileNotFoundException: foo (No such file or directory)

10:21 rhickey: sorry, after -- at the end

10:21 drewr: cmdline.clj contains: (prn *command-line-args*)

10:22 Ah, normal shell semantics. How dare they! :-)

10:22 rhickey: no, that's a Clojure thing I forgot

10:22 -- separates scripts from args

10:23 drewr: Well then, kudos to you for making it logical.

10:23 rhickey: it was a user request :)

10:49 drewr: I'm a little confused about how to create a derived class. Can I use PROXY for that? What does (proxy [java.lang.String]) return exactly?

10:49 I'm not trying to extend String, btw.

10:49 rhickey: String is final

10:49 drewr: Just the first thing that came to mind.

10:50 rhickey: proxy returns an instance of an anonymous class that extends/implements the supplied supers

10:51 drewr: Can I add methods to it?

10:51 I'm trying to utilize a Java library that wants me to create a derived class for and fill in the holes.

10:51 s/ for//

10:52 rhickey: no additional methods, but you can override any methods

10:52 genclass lets you add methods

10:52 if you think about it, since your proxy is anonymous, how could anyone know about any additional methods?

10:54 any support code you need does not need to be in methods, can be in regular Clojure fns

10:54 drewr: I guess the methods are defined in the base class. I've been working in dynamic languages too long.

10:54 They're just meant to be overridden.

10:55 rhickey: so you don't need to add methods, proxy should be adequate

10:55 drewr: Any code of record that makes use of this?

10:55 Wow, GEN-CLASS is a beast.

10:57 rhickey: gen-class solves many java integration problems, but shouldn't be needed for your case unless you need to supply a class name to the Java consumer side

10:58 proxy usages in xml.clj, bean (in proxy.clj), the swing demo in the docs

11:01 ozzilee: rhickey: Is there a way to tell (load-file foo) about macros that I've defined outside of foo? It appears to be trying to resolve symbols inside my macro call.

11:01 Uh, let me know if that doesn't make sense :-)

11:01 rhickey: doesn't yet :(

11:02 did you load the file containing the macros first?

11:02 ozzilee: Yeah. I define the macro in "bar.clj", then load a file "foo.clj" that uses it.

11:03 Let me see if I can come up with a simpler test case than my current rats-nest code.

11:03 rhickey: good idea

11:07 ozzilee: Bugger, looks like that's not the problem. Sorry.

11:14 Bah, stupidity on my part. Changes something from a keyword to a symbol and forgot to change a (keyword?) call.

11:15 *Changed

11:24 Woo! (defget ["foo" x "bar"] x)

11:25 (navigates to localhost:8080/foo/ozzi/bar)

11:25 "ozzi"

11:25 :-)

11:53 drewr: If I've made a Ref like: (def *messages* (ref []))

11:54 ...wouldn't the way to append things to that vector be:

11:54 (alter *messages* (conj *messages* message))

11:54 Sorry, (dosync (alter *messages* (conj *messages* message))).

11:56 cgrand: drewr: (dosync (alter *messages* conj message))

12:00 drewr: cgrand: Thanks. :-)

12:09 Immutability is nice. I just accidentally wrote something concurrently safe.

12:09 rhickey: there you go!

12:12 drewr: I'm still a little confused with Vars though.

12:12 The thing they point at can't be changed, but you can reassign the symbol to something else, right?

12:13 rhickey: vars are a type of reference, so they can be made to refer to something else, just like refs and agents

12:15 there are 3 ways to make them refer to something else, def, which is like old-fashioned global state, binding, which establishes a thread-local meaning, and set!, which changes the thread-local meaning

12:16 drewr: What does vars.html mean by "mutable storage location?"

12:17 rhickey: an atomic reference that can be made to refer to different things over its lifetime

12:18 drewr: Ah, so the thing *in* the storage location isn't mutable. The location is.

12:18 rhickey: right

12:18 drewr: That's what I originally understood but I started to confuse myself.

12:18 rhickey: although you could put a mutable (Java) thing in a reference, it would normally be wrong to do so

12:19 drewr: Because it breaks the abstraction, or because that would be bad anyway?

12:20 rhickey: all the goodness Clojure brings can get destroyed if you mutate things outside of its control

12:20 that said, if you put something that was technically mutable in a reference, but treated it as immutable, that would work

12:20 drewr: That makes sense.

12:21 I was getting concerned lately that Java was leaking too much into Clojure, but I'm finding that once I get the class interop set up with whatever I'm doing I can generally focus only on Clojure.

12:22 rhickey: that's the best approach - get out of Java as soon as possible

12:25 dudleyf: So defs are globally visible with their original binding, but can only be mutated within a thread?

12:26 rhickey: you can rebind them using def again - that's how you fix bugs in running programs, but otherwise you shouldn't use def like assignment

12:27 drewr: rhickey: BTW, I'm going to test drive parallel.clj; just haven't had a chance this week.

12:27 rhickey: have you got a multicore box?

12:28 drewr: Yeah, a MBP.

12:28 rhickey: fine

12:28 drewr: ...and access to many multicore Linux servers that I'd like to try out.

12:28 rhickey: cool

12:31 drewr: Inside a proxy class, is the instance of that class implied when you call a method like a function?

12:32 rhickey: no, you must pass this

12:32 drewr: In xml.clj, (startDocument []) calls that method on the derived ContentHandler class I'm assuming.

12:32 rhickey: that's a definition, not a call

12:33 drewr: Oh you're right. Didn't read the indentation correctly.

12:51 Can I alter the constructor of an proxy class? I'm proxying an abstract class which really wants me to do my own initialization.

12:52 rhickey: you can close over any state you need

13:18 user=> (time (reduce + (range 1000000)))

13:18 "Elapsed time: 173.82 msecs"

13:18 499999500000

13:18 user=> (time (reduce long/+ (range 1000000)))

13:18 "Elapsed time: 33.251 msecs"

13:18 499999500000

13:18 Chouser: wow

13:18 drewr: d00d

13:19 rhickey: use with care:

13:19 user=> (time (reduce int/+ (range 1000000)))

13:19 "Elapsed time: 35.002 msecs"

13:19 1783293664

13:19 note wrong answer

13:19 drewr: Wrap?

13:19 rhickey: right

13:20 but a valuable tool in perf-sensitive inner loops

13:20 drewr: neat.

13:20 rhickey: also float and double versions, which are safe and just plain faster

13:23 user=> (time (fib 35))

13:23 "Elapsed time: 2659.155 msecs"

13:23 9227465

13:23 user=> (time (fibi 35))

13:23 "Elapsed time: 565.412 msecs"

13:23 9227465

13:25 up now, rev 875

13:59 drewr: A protected method should be accessible to children, no?

14:13 I was trying to call a protected method as a client of an instance.

14:13 So how do you override the constructor of the parent class in a PROXY definition.

14:24 I guess the question is how do you create a ctor of the anonymous class.

16:02 rhickey: drewr: no - protected members are not accessible in a proxy

16:03 drewr: Ah, OK.

16:03 I made a real Java class to workaround it.

16:04 Work around it too.

16:05 Chouser: drewr: you can do it with gen-class

16:05 rhickey: the proxy has the same ctors as its super, and you can specify the args in the proxy call. any other data you can close over

16:05 Chouser: stop writing java code! ;-)

16:06 drewr: rhickey: I don't know what you mean by closing over data in the proxy.

16:09 rhickey: all of the 'methods' you define in a proxy call are really Clojure fns, and they can close over the state ofthe context in which they were created - i.e. they are closures

16:10 drewr: OK, I understand that. I think that doesn't help me in this particular case.

16:11 The abstract class I'm extending has (protected) mutators for some of its state.

16:24 rhickey: drer: then gen-class will do it for you - you can expose protected fields, and protected methods become public.

16:33 drewr: Can I not specify genclass.clj after clojure.lang.Repl on the command line?

16:33 I'm trying to get it loaded by default.

16:37 Hm. for(String file : RT.processCommandLine(args)) seems like it would.

16:38 Maybe it got loaded and I'm just not seeing it.

16:42 When I C-c C-k the buffer I can do (doc clojure/gen-class).

17:16 Shouldn't I be able to do (new (gen-class 'Foo))?

17:17 I get Unable to resolve classname: clojure.lang.PersistentList@ebfa2702.

17:17 rhickey: drewr: you should be using either gen-and-load-class or gen-and-save-class

17:20 drewr: (new (clojure/gen-and-load-class 'Foo)) gives me the same result.

17:21 rhickey: gen-and-load-class is something you call once to create the Foo class. Then Foo is available like any other class - (new Foo ...)

17:21 drewr: OK, the side effect of the bytecode loading is what I'm after there. I get it.

17:22 rhickey: right

17:23 drewr: Does it load it in any particular namespace? (new Foo) tells me it can't resolve classname Foo.

17:23 (It successfully generated the bytecode.

17:23 )

17:24 rhickey: you should supply a package name

17:24 to gen-class

17:24 gen-*-class

17:24 drewr: Ah, that worked.

17:27 Can I use :expose if I don't know what the protected member is called? I only know the mutators.

17:27 Doesn't it break encapsulation to have to know the member name?

17:28 rhickey: the mutators will be public in your derived class - so you can use them

17:28 drewr: It's telling me "No matching method found."

17:30 Public setters are working okay.

17:30 rhickey: is the mutator final?

17:31 drewr: Yes. :-(

17:31 rhickey: oh well, that's it

17:31 drewr: Bugger.

17:32 Guess I'll stay with my native Java class.

17:33 rhickey: what were you trying to derive from, if I might ask?

17:33 drewr: This guy: http://www.jibble.org/javadocs/pircbot/org/jibble/pircbot/PircBot.html.

17:34 ,foo

17:34 clojurebot: I don't yet know what "foo" means.

17:34 drewr: ,learn foo

17:34 clojurebot: I don't yet know what "learn foo" means.

17:34 drewr: Well shucks. :-)

17:36 rhickey: ,uh oh

17:36 drewr: It times out after a minute or two.

17:44 Chouser: drewr: do you have a good sandbox for that bot?

17:44 drewr: Chouser: I was in #clojure- all day.

17:45 Chouser: I was thinking an ajaxy REPL might be nice for people to dabble a little without having to install anything.

17:45 ...but obviously I don't want them to be able to do anything to my server.

17:46 drewr: The dangerous parts can be disabled if we can identify what they are.

17:46 rhickey: or use Java's security mechanisms

17:46 * rhickey only knows they exist

17:47 drewr: That's more than I know. ;-)

17:47 Any guesses as to the approach?

17:49 Chouser: I guess I'd start looking at applet containers, but that's a long way from a working solution.

17:49 dudleyf: http://java.sun.com/javase/6/docs/technotes/guides/security/index.html

17:49 Chouser: And also a chroot on the server to be extra safe.

17:49 dudleyf: .. but that's a long way from a working solution ;-)

17:49 Chouser: :-)

17:52 http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html

17:52 a tiny bit closer.

17:54 drewr: Haha, http://yaml.org/.

17:55 Chouser: cute

Logging service provided by n01se.net