What defines an Error?

I wonder how we are to know the appropriate error to raise or to
subclass?

Presently, we simply make a pretty good subjective guess. But I wonder
if
it could be more concrete. Might we be able to define a test for each
error
by which it could be determined? For example, maybe:

class TypeError

  def self.applies?(target, criterion)
    return false unless Exception === target
    return false unless Exception === criterion
    true
  end

  def raise?(target, criterion)
    return false unless applies?(target, criterion)
    return true unless criterion == target
  end

  def self.apply!(target, criterion)
    raise ArgumentError unless applies?(target, criterion)
    raise self if raise?(target, criterion)
  end
end

So #applies? would return false if the given arguments do not make any
sense for the error. And we could use #raise? to see if it would raise
the
error and #apply! to do so.

Does narrowly defining the purpose of errors this way make sense?

Does narrowly defining the purpose of errors this way make sense?

It seems to be too rigorous to me.

I like to keep errors very small and self-descriptive whenever possible.

What I am playing with is to, rather than subclass, perhaps use an

Exception.new(‘too few arguments’) if @found_error

Or something like that, rather than a specific raise(). But I am
strange. :wink:

On Sat, Jan 21, 2012 at 12:46 AM, Marc H. [email protected]
wrote:

Does narrowly defining the purpose of errors this way make sense?

It seems to be too rigorous to me.

It also does not work. There might be only very few errors where
there is just one condition for failure. Normally the condition
depends on the code using the exception type. Even for a TypeError
things are not that clear: you may want to throw if the object in
question is not one of several types or you may want to throw if a
specific method is not implemented etc.

Kind regards

robert

On Friday, January 20, 2012 6:46:11 PM UTC-5, Marc H. wrote:

Or something like that, rather than a specific raise(). But I am
strange. :wink:

:slight_smile: Yea, it does seem strange to define rather empty classes. I’ve
wondered
myself it it would not have just been a whole lot easer if Ruby used
symbol
names instead of classes. But the classes provide a hierarchy, so that’s
the reason. As a bonus it allows us to customize the default error
message
in the class definition. Analysis and testing tools, may then use those
error types to good effect. So I would advise in your example, to try to
match up the closest available error, i.e.

ArgumentError.new(‘too few arguments’) if @found_error

I’ve actually been able to do a little more with error classes too then
I
suspect Matz had any inkling of when he first crated them, indeed there
are
some restrictive “interface contracts”, it you will, that make it not
ideal
in some instances. But working around those, the ability to extend
exception classes has allowed for some nifty approaches to testing.

On Saturday, January 21, 2012 7:12:42 AM UTC-5, [email protected]
wrote:

things are not that clear: you may want to throw if the object in
question is not one of several types or you may want to throw if a
specific method is not implemented etc.

Yea, I thought about it some more and came to a similar conclusion.
Obviously one could create subclasses of TypeError for each of the
particular cases you mention, but it would get pretty unwieldy in short
order. The one that occurred to me that would probably get especially
messy
is IOError.

A compromise position could be used though, such that toplevel errors
are
open, with no such strict definition, but subclasses would have them.
For
example. my previously defined type error could be class SpecificTypeError < TypeError.

Even if not really practical, the question is still a bit intriguing.
What
kind of fine-grain error hierarchy would such a strict evaluational
approach lead to? Is it (ultimately) completely definable?

Marc H. wrote in post #1041861:

I like to keep errors very small and self-descriptive whenever possible.

What I am playing with is to, rather than subclass, perhaps use an

Exception.new(‘too few arguments’) if @found_error

Or something like that, rather than a specific raise(). But I am
strange. :wink:

RuntimeError.new() would be a better default, and indeed there is a
shorter form for this:

raise “too few arguments” if @found_error

RuntimeError is a subclass of StandardError, and StandardError is the
set of “normally rescuable” exceptions. Errors outside of StandardError
are usually critical system errors like NoMemoryError or SyntaxError
which you wouldn’t normally attempt to catch.