2008-05-23
| 00: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? |
| 08:19 | asbjxrn | Any plans for when the next release will be? |
| 08: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. |
| 08:21 | rhickey | There's also a very hot math/inlining optimization I'm working on that I might try to squeeze in |
| 08:22 | cgrand | wow |
| 08:23 | rhickey | Made naive fib 4x as fast |
| 08:23 | cgrand | inlined but still boxed I presume |
| 08:24 | rhickey | Boxed across call boundaries. The cool thing is the inlining is done by HotSpot, if the code path looks right |
| 08:25 | rhickey | so the inlining on my part is just to typed method calls, no primitive op support in code gen |
| 08: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... |
| 08:58 | blackdog | newbie alert, how do i get command line arguments? |
| 08:59 | rhickey | *command-line-args* |
| 08: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 | drewr | Like, another source file. |
| 10:21 | drewr | $ java -cp ~/tmp/src/clojure/clojure.jar clojure.lang.Script cmdline.clj foo bar |
| 10:21 | drewr | 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 | drewr | Ah, normal shell semantics. How dare they! :-) |
| 10:22 | rhickey | no, that's a Clojure thing I forgot |
| 10:22 | rhickey | -- 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 | drewr | 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 | drewr | I'm trying to utilize a Java library that wants me to create a derived class for and fill in the holes. |
| 10:51 | drewr | s/ for// |
| 10:52 | rhickey | no additional methods, but you can override any methods |
| 10:52 | rhickey | genclass lets you add methods |
| 10:52 | rhickey | if you think about it, since your proxy is anonymous, how could anyone know about any additional methods? |
| 10:54 | rhickey | 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 | drewr | 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 | drewr | 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 | rhickey | 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 | ozzilee | Uh, let me know if that doesn't make sense :-) |
| 11:01 | rhickey | doesn't yet :( |
| 11:02 | rhickey | 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 | ozzilee | 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 | ozzilee | Bah, stupidity on my part. Changes something from a keyword to a symbol and forgot to change a (keyword?) call. |
| 11:15 | ozzilee | *Changed |
| 11:24 | ozzilee | Woo! (defget ["foo" x "bar"] x) |
| 11:25 | ozzilee | (navigates to localhost:8080/foo/ozzi/bar) |
| 11:25 | ozzilee | "ozzi" |
| 11:25 | ozzilee | :-) |
| 11:53 | drewr | If I've made a Ref like: (def *messages* (ref [])) |
| 11:54 | drewr | ...wouldn't the way to append things to that vector be: |
| 11:54 | drewr | (alter *messages* (conj *messages* message)) |
| 11:54 | drewr | Sorry, (dosync (alter *messages* (conj *messages* message))). |
| 11:56 | cgrand | drewr: (dosync (alter *messages* conj message)) |
| 12:00 | drewr | cgrand: Thanks. :-) |
| 12:09 | drewr | 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 | drewr | 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 | rhickey | 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 | rhickey | 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 | drewr | 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 | drewr | 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 | rhickey | user=> (time (reduce + (range 1000000))) |
| 13:18 | rhickey | "Elapsed time: 173.82 msecs" |
| 13:18 | rhickey | 499999500000 |
| 13:18 | rhickey | user=> (time (reduce long/+ (range 1000000))) |
| 13:18 | rhickey | "Elapsed time: 33.251 msecs" |
| 13:18 | rhickey | 499999500000 |
| 13:18 | Chouser | wow |
| 13:18 | drewr | d00d |
| 13:19 | rhickey | use with care: |
| 13:19 | rhickey | user=> (time (reduce int/+ (range 1000000))) |
| 13:19 | rhickey | "Elapsed time: 35.002 msecs" |
| 13:19 | rhickey | 1783293664 |
| 13:19 | rhickey | note wrong answer |
| 13:19 | drewr | Wrap? |
| 13:19 | rhickey | right |
| 13:20 | rhickey | 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 | rhickey | user=> (time (fib 35)) |
| 13:23 | rhickey | "Elapsed time: 2659.155 msecs" |
| 13:23 | rhickey | 9227465 |
| 13:23 | rhickey | user=> (time (fibi 35)) |
| 13:23 | rhickey | "Elapsed time: 565.412 msecs" |
| 13:23 | rhickey | 9227465 |
| 13:25 | rhickey | up now, rev 875 |
| 13:59 | drewr | A protected method should be accessible to children, no? |
| 14:13 | drewr | I was trying to call a protected method as a client of an instance. |
| 14:13 | drewr | So how do you override the constructor of the parent class in a PROXY definition. |
| 14:24 | drewr | 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 | drewr | I made a real Java class to workaround it. |
| 16:04 | drewr | 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 | drewr | 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 | drewr | I'm trying to get it loaded by default. |
| 16:37 | drewr | Hm. for(String file : RT.processCommandLine(args)) seems like it would. |
| 16:38 | drewr | Maybe it got loaded and I'm just not seeing it. |
| 16:42 | drewr | When I C-c C-k the buffer I can do (doc clojure/gen-class). |
| 17:16 | drewr | Shouldn't I be able to do (new (gen-class 'Foo))? |
| 17:17 | drewr | 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 | drewr | (It successfully generated the bytecode. |
| 17:23 | drewr | ) |
| 17:24 | rhickey | you should supply a package name |
| 17:24 | rhickey | to gen-class |
| 17:24 | rhickey | gen-*-class |
| 17:24 | drewr | Ah, that worked. |
| 17:27 | drewr | Can I use :expose if I don't know what the protected member is called? I only know the mutators. |
| 17:27 | drewr | 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 | drewr | 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 | drewr | 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 | drewr | ,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 | Chouser | ...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:47 | drewr | That's more than I know. ;-) |
| 17:47 | drewr | 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 | Chouser | http://java.sun.com/javase/6/docs/technotes/guides/security/permissions.html |
| 17:52 | Chouser | a tiny bit closer. |
| 17:54 | drewr | Haha, http://yaml.org/. |
| 17:55 | Chouser | cute |