From: Peter G. <pe...@ar...> - 2005-10-26 14:40:33
|
On Wed, 26 Oct 2005 at 00:11:18 +0200, Andras Simon wrote: > > The larger problem is that global mappings don't give you granularity, > > so you can't map a particular exception class to condition A for call A > > and to condition B for call B, for example. > > That's true, but isn't it the _handling_ of the condition that should > vary from call to call? My - perhaps too simplistic - idea was that > there would be a DEF-JAVA-EXCEPTION macro analogous to (an imaginary, > or jfli's) DEF-JAVA-CLASS, so one can more less automatically work > with conditions instead of having to deal with Java exceptions. I misunderstood what was going on. In the first of the three messages you referenced (a conversation I had totally forgotten until you reminded me) you gave a nice example of how this mechanism is supposed to work: (define-condition illegal-argument (error) ()) (register-java-exception "java.lang.IllegalArgumentException" 'illegal-argument) (jstatic (jmethod "java.lang.String" "valueOf" "int") "java.lang.String" 23.1) Debugger invoked on condition of type ILLEGAL-ARGUMENT: # Restarts: 0: ABORT Abort handling SLIME request. So far so good. I think the idea of a DEF-JAVA-EXCEPTION macro is a good one, too. So instead of: (define-condition illegal-argument (error) ()) (register-java-exception "java.lang.IllegalArgumentException" 'illegal-argument) you could just do: (def-java-exception illegal-argument "java.lang.IllegalArgumentException") Or maybe even just (def-java-exception "java.lang.IllegalArgumentException") and some sort of magic would happen that would define a condition called java.lang.illegal-argument-exception. OK. In the last of the three referenced messages, you suggested: And now I think that adding a few slots to conditions that are signaled when Java exceptions are raised would be a good thing. To keep entropy at bay, a condition JAVA-EXCEPTION could be defined with just two slots: MESSAGE and STACK-TRACE. It would report the MESSAGE only. Users could subclass this condition, and expect the two slots to be filled in when it is signaled. So DEF-JAVA-EXCEPTION would define a condition that would be a subclass of JAVA-EXCEPTION (rather than ERROR, as in the examble above). OK. (But I think we might only need one slot, which would be filled in with a JAVA-OBJECT that wrapped the original Java Throwable object. That way we'd never lose any of the information from the original Throwable, if by some chance it contained more than MESSAGE and STACK-TRACE.) > > We probably do need to report exceptions thrown by Java code invoked by > > JCALL and friends, but I think it might make more sense to define some > > sort of JAVA-CONDITION that would just encapsulate the thrown Java > > exception. Then user code could simply HANDLER-BIND or HANDLER-CASE > > JAVA-CONDITION and dispatch on the encapsulated exception. > > It's not clear to me how one could dispatch on the Java exception. I was thinking of JAVA-CONDITION as being roughly equivalent to your JAVA-EXCEPTION, except with just one slot for the original Java Throwable. Then the user could dispatch on the contents of that slot by hand in the HANDLER-CASE clause: (handler-case (jcall x y) (java-exception (c) (let* ((throwable (java-exception-throwable c)) (class-name (jclass-of throwable))) (cond ((equal class-name "java.lang.ClassCastException") (do-something)) ((equal class-name "java.lang.NullPointerException") (do-something-else)))))) Which, admittedly, is pretty awkward compared to: (handler-case (jcall x y) (java.lang.class-cast-exception (c) (do-something)) (java.lang.null-pointer-exception (c) (do-something-else)) > And isn't the whole point of all this is to not to have to worry about > exceptions, but only conditions? But I may very well be missing > something! No, I think you're absolutely right. But I still have a question (maybe more than one, but one for now). Consider an application that uses multiple third-party library modules. One module might do (define-condition null-pointer-error (java-exception) ()) (register-java-exception "java.lang.IllegalArgumentException" 'null-pointer-error) and another module might do (define-condition null-pointer-exception (java-exception) ()) (register-java-exception "java.lang.IllegalArgumentException" 'null-pointer-exception) It seems like whichever of these modules is loaded last will get its way with the handling of NullPointerExceptions, and the other one won't see them at all. This is what I was getting at when I complained that global mappings don't give you granularity. What should we do about this? -Peter |