Feature #5898

raise and Exception#initialize

Calling #raise with a message parameter passes the argument on the Exception class' initialize method. But it does not support any additional arguments if the initialize method has been defined otherwise. Nor is the last optional argument, caller, passed to the initializer. All of which makes for a rather confusing mishmash of an interface between #raise and Exception#initialize.

Ideally I would think whatever arguments are passed to #raise would likewise be passed on to Exception#initialize, e.g.

Alas, because caller can be passed to #raise this causes an error, as it thinks bar ought to be the caller array. So unless others see a way around it that I do not, this idealized scenario simply is not possible.

So I propose a second best approach. Notice that if caller is passed to #raise it is not being passed on to the #initialize method unlike the message argument. Instead #set_backtrace is being used to set the caller. I propose that the message argument be handled in the same way, and a new method #set_message(msg) be added to the Exception class to handle it.

This would then allow the initializer of subclasses to be freed up to be defined in other ways, should a specialized exception be able to make good use of a variant interface Which, btw, is the exact circumstance I presently find myself in for one of my projects. Consequently I had no choice by to define the #initialize method to take an initial blank argument that will almost always be set to +nil+.

So I propose a second best approach. Notice that if caller is
passed to #raise it is not being passed on to the #initialize
method unlike the message argument. Instead #set_backtrace is
being used to set the caller. I propose that the message argument
be handled in the same way, and a new method #set_message(msg) be
added to the Exception class to handle it.

How do you tell if the second argument is a part of messages, or a
caller?

Of course, I could do that, and that might be fine if it were only me and my program that would ever raise that error. But that's not the case. It may well be used by others. So to break the #raise "contract" would be very bad form. In other words, I am not going to try to explain to my end-developers that certain exceptions are "special" and can't be raised in standard fashion, but always must be done so with #new. And that's really the jist of my point. We shouldn't need to sacrifice one interface for the other.

Maybe I've over explained (as I am wont to do) and I should just put it this way: It would be good if one could customize the #initialize method of an Exception subclass without causing #raise to break when used in the typical raise ErrorClass, "message" fashion.