(I asked about this a year ago, but must have forgotten about it.)
There are many cases where a user invoked a command that doesn't make any sense, so the RPC can't complete with a meaningful answer, but it would also be overkill to throw the user into a debugger. It would be nice to abort the RPC with a message to the user, such as `Package does not exist' for `slime-repl-set-package' or `Undefined function' for `slime-disassemble-symbol'. It looks like there was once a time when a message could be supplied with a :ABORT result from an RPC, and there are some vestigial remnants of support for it -- `slime-rex' forms with (:ABORT &OPTIONAL REASON), and indeed the documentation of `slime-rex' says that the reason is not optinoal --, but there are many other uses that prohibit a reason from being supplied.
Is there a good reason for :ABORT responses not to have an optional message associated with them, or would a patch be welcomed for all of the uses of `slime-rex' to consistently accept an optional message?
Taylor R Campbell campbell@mumble.net writes:
(I asked about this a year ago, but must have forgotten about it.)
There are many cases where a user invoked a command that doesn't make any sense, so the RPC can't complete with a meaningful answer, but it would also be overkill to throw the user into a debugger. It would be nice to abort the RPC with a message to the user, such as `Package does not exist' for `slime-repl-set-package' or `Undefined function' for `slime-disassemble-symbol'.
The nice thing about the current behaviour is that it's (perhabs arguably) convenient if the host Lisp provides appropriate continuation restarts.
It looks like there was once a time when a message could be supplied with a :ABORT result from an RPC, and there are some vestigial remnants of support for it -- `slime-rex' forms with (:ABORT &OPTIONAL REASON), and indeed the documentation of `slime-rex' says that the reason is not optinoal --, but there are many other uses that prohibit a reason from being supplied.
Is there a good reason for :ABORT responses not to have an optional message associated with them, or would a patch be welcomed for all of the uses of `slime-rex' to consistently accept an optional message?
I have done some work to take these messages into account at the REPL (cf. entry 2007-05-14) -- however, the problem is not so much with "accepting messages from Slime", but that not much code in SWANK appropriately calls SWANK:ABORT-REQUEST (and maybe rightly so!)
For instance, take the following into consideration:
CL-USER> (swank::decode-keyword-arg '#(1 2 3)) ; Evaluation aborted: Bad keyword item of formal argument list
CL-USER> (swank::decode-keyword-arg '(#(1 2 3))) ; ==> thrown into debugger with ; ; The value #(1 2 3) is not of type SYMBOL. ; [Condition of type TYPE-ERROR]
The difference is that the first case is explicitly handled with an invokation of ABORT-REQUEST. Similiarly to make the cases you mentioned above actually return a message, the respective functions of SWANK would have to be modified to test for bad data, and invoke ABORT-REQUEST accordingly.
That is not to say that I'm against your proposed changes to slime.el. (And of course, I can figure that you probably want that for SLIME48, so the SWANK side is not as much of a matter for you.)
-T.
Date: Fri, 29 Jun 2007 09:22:26 +0200 From: "Tobias C. Rittweiler" tcr@freebits.de
The nice thing about the current behaviour is that it's (perhabs arguably) convenient if the host Lisp provides appropriate continuation restarts.
Restarts do make it possible to work around these situations, but I'd hardly call it `convenient'. The situations to which I refer are those in which there really is a uniquely best course of action -- for Emacs to present a message to the user, and for the user to behave better --, so entering a debugger at all is just an impediment to the user's flow. Using the condition system at all for such cases doesn't make much sense: the whole purpose of it is to allow programs to defer to other parts of the program the decision of what course of action to take, when there are multiple possibilities between which none is obviously best.
I have done some work to take these messages into account at the REPL (cf. entry 2007-05-14)
Oops! I was looking at CVS from 2007-05-13. I shall endeavour to remember to update CVS before making inquiries on the mailing list...
-- however, the problem is not so much with "accepting messages from Slime", but that not much code in SWANK appropriately calls SWANK:ABORT-REQUEST (and maybe rightly so!)
[...]
That is not to say that I'm against your proposed changes to slime.el. (And of course, I can figure that you probably want that for SLIME48, so the SWANK side is not as much of a matter for you.)
It is true that I have an obvious interested in SLIME48, but I think that it is also worth considering in Common Lisp. My (possibly wrong) idea of the architecture of CL Swank is that there is the back end, which implements non-portable extensions to Common Lisp that are useful in IDEs, and the implementation of the RPCs. The back end is (theoretically) useful independent of the specific integration with Emacs, and the RPCs are for the most part just wrappers around the functionality of Common Lisp and the Swank back end necessary to present information palatably to Emacs. In my model, the RPC functions (i.e. everything defined with DEFSLIMEFUN) are the only places in the code that ABORT-REQUEST should ever be invoked in code, because they themselves are expected to be invoked only by remote call from Emacs; everything else should use the condition system to report problems.
Now, obviously, real errors in RPC implementations should trigger the debugger, and the debugger is always an acceptable substitute if an RPC implementation fails to properly check its arguments. But I think that it would be preferable for anything invoked by Emacs through the RPC server to call ABORT-REQUEST with a useful report, and for anything intended to be invoked by arbitrary Common Lisp clients to use the condition system.
Personally, in the case of DECODE-KEYWORD-ARG, I'd use the condition system to report errors: it looks to me like any error there is a bug worthy of debugging anyway, because it should only ever receive its arguments from within the Common Lisp system, which is presumably in an inconsistent state if it yields an invalid argument list.
I could also have a completely wrong idea about this, because I didn't design it, and never discussed its design at any great length with its designers; this is just what I have concluded from my understanding of the code.
* Taylor R Campbell [2007-06-29 00:40+0200] writes:
Is there a good reason for :ABORT responses not to have an optional message associated with them, or would a patch be welcomed for all of the uses of `slime-rex' to consistently accept an optional message?
I dislike this idea. Why can't the function just return an error indicator together with the error message if it can't complete normally? I think we shouldn't add an exception system for RPCs. Tagged return values are easy to understand and good enough for the job.
Also, dropping into the debugger seems to be the proper action to take. If SLIME doesn't handle the returned value it's obviously a bug. (And the bug will be fixed sooner if the debugger pops up.)
Arbitrary user code may (or not) assume the presence of an ABORT restart, but that's quite a different story.
Helmut.
Date: Fri, 29 Jun 2007 13:54:31 +0200 From: Helmut Eller heller@common-lisp.net
I dislike this idea. Why can't the function just return an error indicator together with the error message if it can't complete normally? I think we shouldn't add an exception system for RPCs. Tagged return values are easy to understand and good enough for the job.
Is it really better to extend N different callees of `slime-eval' and friends to accept a tagged result to distinguish OK responses from errors, when the RPC mechanism already has one? All of the callers where it is possible for a user error to arise would have to be modified to expect a possible error response -- say, remote callers of SWANK:SET-PACKAGE when the package doesn't exist, SWANK:SWANK-TOGGLE-TRACE or a number of other similar operations when the function in question is not defined, SWANK:GET-REPL-RESULT when the result is unavailable, and so on.
Also, dropping into the debugger seems to be the proper action to take. If SLIME doesn't handle the returned value it's obviously a bug. (And the bug will be fixed sooner if the debugger pops up.)
Sorry, I'm a little unclear: Do you mean that it is the proper action to take to drop into the debugger for the above examples, where there is a single uniquely best course of action (namely, for the user to do something else after being presented with an error message); or that all of the RPC interfaces where user errors are possible should be changed to support them, and that any callers that don't deal with the errors gracefully should drop into the debugger?
* Taylor R Campbell [2007-06-29 19:13+0200] writes:
Date: Fri, 29 Jun 2007 13:54:31 +0200 From: Helmut Eller heller@common-lisp.net
I dislike this idea. Why can't the function just return an error indicator together with the error message if it can't complete normally? I think we shouldn't add an exception system for RPCs. Tagged return values are easy to understand and good enough for the job.
Is it really better to extend N different callees of `slime-eval' and friends to accept a tagged result to distinguish OK responses from errors, when the RPC mechanism already has one? All of the callers where it is possible for a user error to arise would have to be modified to expect a possible error response -- say, remote callers of SWANK:SET-PACKAGE when the package doesn't exist, SWANK:SWANK-TOGGLE-TRACE or a number of other similar operations when the function in question is not defined, SWANK:GET-REPL-RESULT when the result is unavailable, and so on.
The plan is to remove the mechanism. Changing the caller together with the callee is a small price to pay.
Also, dropping into the debugger seems to be the proper action to take. If SLIME doesn't handle the returned value it's obviously a bug. (And the bug will be fixed sooner if the debugger pops up.)
Sorry, I'm a little unclear: Do you mean that it is the proper action to take to drop into the debugger for the above examples, where there is a single uniquely best course of action (namely, for the user to do something else after being presented with an error message); or that all of the RPC interfaces where user errors are possible should be changed to support them, and that any callers that don't deal with the errors gracefully should drop into the debugger?
The callees where it makes sense should be changed, together with the callers. Dropping into the debugger is also OK. Silently ignoring bugs or errors is never OK.
Helmut.