2008-09-02
| 07:50 | parth_m | Hello |
| 07:52 | parth_m | If I am to write a print-decorator http://groups.google.com/group/clojure/msg/cb7a45124bbf92f5 what would be a good way to get the name of the function being decorated at runtime? |
| 07:53 | parth_m | In the method suggested, having to switch namespaces seems a little weird. |
| 07:53 | parth_m | If I don't switch ns, there is stack overflow. |
| 08:01 | hoeck | parth_m: why not just taking the functions classname at runtime? |
| 08:02 | parth_m | hoeck: as (class f)? |
| 08:03 | parth_m | This works, actually just a print also works but it shows the compiled form .. e.g user.foo__2372@5388b5 |
| 08:03 | parth_m | I was wondering if I can get "foo" |
| 08:03 | hoeck | of course, with some string and regex matching |
| 08:04 | hoeck | and it has the advantage of working with (named) anonymous functions (which i use very often) :) |
| 08:05 | parth_m | Yes .. I could do that. |
| 08:05 | parth_m | I am not too clear on using meta data. I know the info exists ... just not sure how to get it. |
| 08:05 | parth_m | user=> (meta (var foo)) |
| 08:05 | parth_m | {:arglists ([]), :file "NO_SOURCE_FILE", :line 9, :ns #<Namespace: user>, :name foo} |
| 08:06 | parth_m | So, "foo" is definitely there somewhere ... but in the decorator scenario it doesn't seem to work. Throws an exception: http://groups.google.com/group/clojure/msg/91b028c63ec440d6 |
| 08:10 | parth_m | Its not a big thing ... I was just wondering in case there is a idiomatic way of doing this. |
| 08:11 | hoeck | mhh, aren't vars resolved at compile-time? |
| 08:12 | parth_m | I suppose so. |
| 08:14 | parth_m | But if we pass "foo" to "print-decorate" isn't the meta-data attached to "foo"? This may be a silly question but I still don't understand clojure meta-data fully. |
| 08:15 | hoeck | no, metadata is only attached to vars and a few clojure data-structures |
| 08:16 | parth_m | Ah. I think I get it now. So what gets passed is a function ... so there is no metadata attached. Right? |
| 08:17 | hoeck | yes, the metadata you create with defn gets only attached to the var holding the function object |
| 08:18 | hoeck | but the AFn Class actually has a withMeta method, but it throws an unsupported operation exception, so in theory, you could attach metadata to functions too |
| 08:19 | parth_m | Having metadata with functions would be nice ... I suppose that needs to fit into the overall introspection picture. |
| 08:20 | parth_m | Thanks hoeck. I understand this much better now. |
| 08:20 | parth_m | So when we do #'foo its a var. and just 'foo' is a function being passed. |
| 08:25 | hoeck | yeah, #'foo is a shortcut for (var foo), and foo evaluates to the value of foo (in this case a function) |
| 08:26 | parth_m | Common Lisp had me confused ... I thought #'foo was a function as with CL :) |
| 08:26 | parth_m | Thanks hoeck. Will use the class for now. |
| 08:27 | hoeck | me too, but clojure has only one namespace for functions and values, which I find pretty handy btw |
| 08:28 | parth_m | I agree. Its much nicer to say (map foo ..) rather than (map #'foo ..) |
| 09:23 | cemerick | rhickey: it turns out that the NB profiler chokes on clojure in general (though your genclass patch stops it from tossing a hard error); the process being profiled "hangs" (for lack of a better term) as soon as clojure.lang.RT is statically referenced. |
| 09:24 | rhickey | cemerick: that's bad, last time I tried it it ran no problem but only profiled the Java bits of Clojure |
| 09:24 | rhickey | cemerick: I see you got the 18-arg patch |
| 09:25 | cemerick | yeah I did; so, you set up the profiler to instrument only clojure.lang.*? |
| 09:26 | rhickey | I don't remember too well, but I think I asked for everything but standard Java libs, got only Java calls |
| 09:27 | cemerick | FWIW, dumping profiling data via -hprof options works just fine (which I load up in hpjmeter) -- crude, but effective. |
| 09:31 | rhickey | soneone suggested JiP at one point: http://jiprof.sourceforge.net/ |
| 09:31 | rhickey | someone |
| 10:11 | cemerick | rhickey: thanks for the link; I think I'll try yourkit next, just to see if NB is the problem, or if clojure/asm/whatever is somehow at odds with JVMPI itself. |
| 11:42 | cemerick | yourkit profiles the same NB project without a problem; however, a super-small project I put together that contains only clojure.jar and a main class that references clojure.lang.RT is successfully profiled by NB....so, now I'm pretty confused. |
| 15:13 | lisppaste8 | jamii pasted "qt-repl" at http://paste.lisp.org/display/66213 |
| 16:19 | jgracin | rhickey, hi! how come there are no tests in Clojure's implementation? |
| 16:19 | jgracin | I'm obviously asking about your opinion on automatic testing. :-) |
| 16:32 | rhickey | jgracin: no one's written any yet |
| 16:32 | abrooks_ | Heh. |
| 16:33 | rhickey | a test suite would be a welcome contribution |
| 16:35 | Chouser | people have talked some about how a test suite would be structured. It'll happen eventually. |
| 16:36 | rhickey | until then I'll just keep trying to get it right the first time :) |
| 16:40 | jgracin | rhickey, nice strategy. :-) |
| 17:36 | lisppaste8 | jamii pasted "qt repl and slots in action" at http://paste.lisp.org/display/66224 |
| 17:44 | jamii | How do I create instances of generic classes? |
| 17:44 | jamii | eg Signal1<Object> |
| 17:44 | Chouser | ignore the generic part |
| 17:44 | Chouser | so, just Signal1 |
| 17:44 | jamii | Hmmm. Qt might not like that. Ill give it a try |
| 17:51 | jamii | How do I use a nested class? I would have thought (import '(com.trolltech.qt.QSignalEmitter Signal0)) would work |
| 17:52 | kotarak | Try QSignalEmitter$Signal0 |
| 17:53 | jamii | Yep, that worked. |
| 17:53 | jamii | Is the $ specific to imports? |
| 17:53 | kotarak | No, it's for nested classes. |
| 17:53 | jamii | Ok. Cheers |
| 18:11 | jamii | Damn, I wish new wasnt a macro. |
| 18:14 | kotarak | It's not. It's a special form, AFAIK. What do you want to do? |
| 18:18 | jamii | kotorak: I need to create one of Signal0 to Signal10 depending on the argument number |
| 18:19 | jamii | something like: (defn signal [n] (new (sym "Signal" (str n)))) |
| 18:20 | jamii | I dont think its possible with new though. Is there another primitive for constructing objects? |
| 18:20 | kotarak | Not that I am aware of... |
| 18:21 | jamii | Oh well. cond it is then |
| 18:21 | kotarak | You could resolve to ugly anti-features: |
| 18:21 | kotarak | (let [c TheClassYouNeed] (eval `(new ~c))) |
| 18:23 | jamii | That'll do. It doesnt have to be pretty |
| 18:23 | kotarak | cond is probably the better solution. Also not pretty, but one has a good conscience. |
| 19:42 | Chouser | is it any prettier to do the evals up front? |
| 19:43 | jamii | Is there a way to add java fields to a class using proxy? Signals can only appear as a field of a subclass of QSignalEmitter. Which is a little annoying. I've been trying to do this using gen-and-load-class but the :state option is causing problems |
| 19:43 | Chouser | (def sigs (vec (for [i (range 10)] (eval `(fn [] (new ~(symbol (str "Signal" i)))))))) |
| 19:44 | jamii | Chouser: Im using almost exactly that code :-) |
| 19:44 | Chouser | jamii: no, you'll have to use gen-class to add a field. |
| 19:44 | jamii | So i need to use :state and :init |
| 19:45 | jamii | How does the scoping work in :init - it keeps complaining that my init function isnt defined |
| 19:45 | jamii | This is what I have at the moment: |
| 19:45 | jamii | (defn- make-signal-holder [n] |
| 19:45 | jamii | (gen-and-load-class |
| 19:45 | jamii | (symbol (str "slot.SignalHolder" n)) |
| 19:45 | jamii | :extends QSignalEmitter |
| 19:45 | jamii | :constructors {[(eval (symbol (str "QSignalEmitter$Signal" n)))] []} |
| 19:45 | jamii | :init 'signal-holder-init |
| 19:45 | jamii | :state 'signal)) |
| 19:46 | Chouser | you're running the last release, or latest SVN? |
| 19:46 | jamii | Somewhere in between... svn 1-2 weeks old |
| 19:47 | Chouser | ok, your defn probably needs to use the name SignalHolder-signal-holder-init |
| 19:49 | rhickey | jamii: for no-arg dynamic new - (.newInstance (Class/forName str)) |
| 19:49 | jamii | rhickey: Thanks |
| 19:52 | jamii | Hang on, that needs to be (.. (Class/forName str) (getConstructor types) (newInstance)) |
| 19:53 | rhickey | jamii: are there args? your examples didn't have any |
| 19:54 | jamii | Sorry. The examples didnt have any because the jambi docs are wrong. There is in fact a single mystery arg |
| 19:55 | rhickey | (clojure.lang.Reflector/invokeConstructor (Class/forName str) (to-array args)) |
| 19:56 | jamii | cool |
| 19:57 | rhickey | better still, use RT.classForName which will leverage Clojure's classpath stuff |
| 19:59 | rhickey | (resolve (symbol "java.util.ArrayList")) is another way to look at it |
| 20:06 | jamii | It seems that jambi is not fooled by gen-and-load-class: "java.lang.RuntimeException: Signals must be declared as members of QSignalEmitter subclasses" |
| 20:06 | rhickey | jamii: are you extending that class? |
| 20:07 | jamii | Yes |
| 20:07 | jamii | And putting the signal in the :state slot |
| 20:09 | jamii | google has nothing. Does :state produce a real field. Maybe I should try a property instead |
| 20:10 | rhickey | http://doc.troll.no/qtjambi-4.3.4_01/doc/html/com/trolltech/qt/qtjambi-signalsandslots.html says: All normal member methods can be used as slots, so there are no specific requirements for a method to function as a slot. |
| 20:11 | jamii | Signals and slots are not the same. I've managed to wrap clojure functions as slots quite easily. The trouble is that new signals have to be created as members of a QSignalEmitter |
| 20:18 | rhickey | jamii: :state does produce a public final field of type Object. |
| 20:19 | rhickey | but it seems like you can define accessor methods for signals, rather than use fields, as implied by "It is customary to declare signals as public rather than to provide access methods for them." |
| 20:20 | jamii | I'll try using :exposes |
| 20:21 | rhickey | jamii: that's just for exposing an existing protected field of a superclass |
| 20:21 | jamii | Damn |
| 20:31 | Chouser | does final mean everything inside that object will be immutable, or is it just that the top-level value of that field cannot change? |
| 20:36 | rhickey | Chouser: the latter |
| 21:09 | jamii | To import a java file in clojure do I have to do anything beyond compile it and set the classpath? |
| 21:18 | shoover | jamii: That should do it. If the file is compiled to a .class, put the directory on the classpath. If the .class is part of a jar, put the jar on the classpath. |
| 21:20 | jamii | Ok, i probably have a typo buried deep in the folder hierarchy |
| 21:34 | jamii | rhickey: Turns out signals have to be declared inside the scope of the QSignalEmitter subclass. Dropping into java seems to be the way forward |
| 21:34 | jamii | s/declared/instantiated |
| 21:35 | jamii | public Signal0 signal = new Signal0(); is the single only way it will be accepted |
| 22:05 | Chouser | no way to get to "this" from the init function? |
| 22:27 | Chouser | wouldn't matter anyway -- Qt's using getDeclaredFields to poke through the Emitter's parentage looking for a matching Signal member. |
| 22:43 | jamii | Chouser: I have it sort of working. It gives me an exception the first time I use a signal and works fine thereafter. I'm tempted to just have the wrapper force and catch that first exception before returning the signal. A little hacky though |
| 22:43 | Chouser | hm... |
| 22:47 | Chouser | that's with Java code for the signals? |
| 22:48 | jamii | I hava a java class that looks like: |
| 22:48 | jamii | public static class QField extends QObject { |
| 22:48 | jamii | public QField() { |
| 22:48 | jamii | super(); |
| 22:48 | jamii | } |
| 22:48 | jamii | |
| 22:48 | jamii | public Object field; |
| 22:48 | jamii | } |
| 22:49 | jamii | Because I couldnt figure out how to do fields properly from withing clojure |
| 22:49 | jamii | Then I set! field with a new signal. The mystery arg in the signal turned out to be because they're non-static inner classes - they need an instance of their container class which in this case is QField |
| 23:03 | jamii | svn ~2 weeks out of date |
| 23:04 | jamii | oops |
| 23:12 | jamii | java.lang.RuntimeException: Signal initialization failed |
| 23:12 | jamii | Thats a new on |
| 23:12 | jamii | *one |
| 23:15 | jamii | Chouser: All signals are failing on the first emit with "Signals must be declared as members of QSignalEmitter subclasses". Zero arity signals work fine afterwards but others fail with "Signal initialization failed". I have no idea whats going on |
| 23:17 | Chouser | I'm looking at the source for resolveSignal() in QSignalEmitterInternal -- but I'm don't really understand it. |
| 23:38 | jamii | fetchSignal is native. im getting the qt source now |
| 23:59 | jamii | I think I have it |