Feature #8912
closedException.raise
Description
=begin
When we have a custom exception class with a custom (({initialize})) method whose arity is not (({1})):
class MyException < StandardError
def initialize x, y
super("Something went wrong with #{x.inspect} because #{y}, blah blah")
end
end
in order to raise it, we have to create a new instance of it explicitly using (({new})), and embed that under (({Kernel#raise})).
raise(MyException.new(:foo, :bar))
This is inconvenient, and does not look object oriented. I propose that there should be (({Exception#raise})), which is public, so that we can do:
MyException.raise(:foo, :bar)
A Ruby implementation may be like this:
class Exception
def self.raise *args; Kernel.send(:raise, *args) end
end
This will disallow us from calling the private method (({Kernel#raise})) (without an explicit receiver) within the context of an (({Exception})) class unless we use (({send})), but I think such use case is rare, and that should not be a problem.
=end
Updated by sawa (Tsuyoshi Sawada) about 10 years ago
=begin
I made a mistake. I meant, an implementation may be:
class Exception
def self.raise *args; Kernel.send(:raise, new(*args)) end
end
=end
Updated by matz (Yukihiro Matsumoto) about 10 years ago
- Status changed from Open to Feedback
I am not sure if there's significant practical difference between
raise(MyException.new(:foo,:bar))
and
MyException.raise(:foo,:bar)
It seems very trivial for me.
I guess you hate to call the function (private method of Kernel) #raise?
Can you elaborate?
Matz.
Updated by sawa (Tsuyoshi Sawada) about 10 years ago
matz, thank you for the comment.
I think that raising an error is a peculiar property of an instance of Exception
. Every time we raise
, we raise one and only one exception, and nothing else. No other type of object can be raised. From object oriented point of view, this tells us that the method should belong to the Exception
class, not Kernel
.
Furthermore, it is rare that we want to create an instance of an Exception without raising it. If Exception#new
exists, there is even more reason to have Exception#raise
. The latter is more usable than the former.
In fact, method "raise" should be considered as a constructor with a side effect (of raising the exception). Various constructors are defined as class methods, and I don't understand why that is not the case for exceptions.
From a practical point of view, I feel repeating the extra pairs of parentheses cumbersome.
Updated by nobu (Nobuyoshi Nakada) about 10 years ago
- Subject changed from Exception#raise to Exception.raise
- Description updated (diff)
=begin
How can you pass erred location and backtrace?
You can call (({Kernel.raise})) as:
class Exception
def self.raise(*args) Kernel.raise(new(*args)) end
end
And you seem talking about (({Exception.raise})), not (({Exception#raise})).
=end
Updated by matz (Yukihiro Matsumoto) about 10 years ago
As Nobu pointed out, we need to use the proper terms:
- Exception.raise instead of Exception#raise
- Exception.new instead of Exception#new
We have to distinguish class methods and instance methods.
Then I think we need a way to separate allocating and raising.
By providing Exception.raise (and discouraging Kernel#raise), there's no sufficient way to raise pre-allocated exceptions.
Kernel raise takes either exception class or exception instance.
If we really need to emphasize OO way in raising exception as you claim, I'd rather add Exception#raise, i.e.
MyException.new(:foo,:bar).raise
But in reality, I prefer traditional
raise MyException.new(:foo,:bar)
because 'raise' is a core operation, that often is implemented by the reserved keyword in other languages,
and maybe we will replace it by (somewhat-soft) keyword in the future.
Matz.
Updated by fuadksd (Fuad Saud) about 10 years ago
Raising doesn't feel like a proper responsability of the exception.
On Sep 15, 2013 3:42 AM, "matz (Yukihiro Matsumoto)" matz@ruby-lang.org
wrote:
Issue #8912 has been updated by matz (Yukihiro Matsumoto).
As Nobu pointed out, we need to use the proper terms:
- Exception.raise instead of Exception#raise
- Exception.new instead of Exception#new
We have to distinguish class methods and instance methods.
Then I think we need a way to separate allocating and raising.
By providing Exception.raise (and discouraging Kernel#raise), there's no
sufficient way to raise pre-allocated exceptions.
Kernel raise takes either exception class or exception instance.If we really need to emphasize OO way in raising exception as you claim,
I'd rather add Exception#raise, i.e.MyException.new(:foo,:bar).raise
But in reality, I prefer traditional
raise MyException.new(:foo,:bar)
because 'raise' is a core operation, that often is implemented by the
reserved keyword in other languages,
and maybe we will replace it by (somewhat-soft) keyword in the future.Matz.
Feature #8912: Exception.raise
https://bugs.ruby-lang.org/issues/8912#change-41820Author: sawa (Tsuyoshi Sawada)
Status: Feedback
Priority: Normal
Assignee:
Category:
Target version:=begin
When we have a custom exception class with a custom (({initialize}))
method whose arity is not (({1})):class MyException < StandardError def initialize x, y super("Something went wrong with #{x.inspect} because #{y}, blah
blah")
end
endin order to raise it, we have to create a new instance of it explicitly
using (({new})), and embed that under (({Kernel#raise})).raise(MyException.new(:foo, :bar))
This is inconvenient, and does not look object oriented. I propose that
there should be (({Exception#raise})), which is public, so that we can do:MyException.raise(:foo, :bar)
A Ruby implementation may be like this:
class Exception def self.raise *args; Kernel.send(:raise, *args) end end
This will disallow us from calling the private method (({Kernel#raise}))
(without an explicit receiver) within the context of an (({Exception}))
class unless we use (({send})), but I think such use case is rare, and that
should not be a problem.
=end