Just a quick question about raising exceptions in IronRuby libraries.
Should we just simply throw a new CLR exception or do we need to use the
ExceptionOps stuff when creating exceptions.
As an example, in FloatOps, I have a method for divmod:
[RubyMethod("divmod")]
public static RubyArray DivMod(double self, double other) {
// Unlike modulo, divmod throws an error if the quotient is not
a proper number.
// This appears to be an inconsistency in MRI.
double quotient = self / other;
if (Double.IsNaN(quotient) || Double.IsInfinity(quotient) ) {
throw new FloatDomainError("NaN");
}
return InternalDivMod(self, other);
}
If the quotient is not valid then we raise a FloatDomainError. The
FloatDomainError class uses ExceptionOps.MakeMessage and also
ExceptionOps.InitializeException in the constructor. A quick look at
InitializeException puts some data into the Exception.Data property, which I
am assuming, without going any deeper, is required by the Ruby runtime to
handle the exception correctly.
This is all well and good, but when you look at BignumOps, I have a method
for to_s:
[RubyMethod("to_s")]
public static object ToString(BigInteger self, uint radix) {
try {
// TODO: Can we do the ToLower in BigInteger?
return new MutableString(self.ToString(radix).ToLower());
} catch (ArgumentOutOfRangeException x) {
throw ArgumentErrorOps.Factory(new
MutableString(x.Message));
}
}
Now this one needs to raise an ArgumentError, which is actually a Ruby
wrapper around System.ArgumentException (i.e. ArgumentError is a pure Ruby
class that "extends" the CLR class System.ArgumentException. Now I
could
have just created a new ArgumentException here but since this doesn''t
call,
apart from anything else, ExceptionOps.InitializeException, I felt I needed
to use the ArgumentErrorOps.Factory method to create the exception. I
believe the primary reason for this method is so that the DLR can create
exceptions from pure Ruby code, i.e. raise ArgumentError, ...
Am I being over-cautious here and should I be happily creating CLR
exceptions directly and not worrying too much? I expect and hope that this
is the case, as otherwise how would the DLR deal with cases where pure .NET
classes throw pure CLR exceptions?
Cheers,
Pete
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://rubyforge.org/pipermail/ironruby-core/attachments/20071206/cad6ece3/attachment-0001.html
And to add further confusion there are also RubyExceptions.CreateXXXError methods available. What to use? Pete -------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/ironruby-core/attachments/20071206/32c622bf/attachment.html
Our automatic exception mapping mechanism maps ArgumentOutOfRangeExceptions to
RangeErrors. Since the correct behavior in this case appears to be raising an
ArgumentError, it makes sense to catch and rethrow.
I''m attaching a PDF that shows how we map CLR exceptions to Ruby
exceptions.
Thanks,
-John
From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at
rubyforge.org] On Behalf Of Peter Bacon Darwin
Sent: Thursday, December 06, 2007 2:40 AM
To: ironruby-core at rubyforge.org
Subject: [Ironruby-core] Raising Exceptions
Just a quick question about raising exceptions in IronRuby libraries. Should we
just simply throw a new CLR exception or do we need to use the ExceptionOps
stuff when creating exceptions.
As an example, in FloatOps, I have a method for divmod:
[RubyMethod("divmod")]
public static RubyArray DivMod(double self, double other) {
// Unlike modulo, divmod throws an error if the quotient is not a
proper number.
// This appears to be an inconsistency in MRI.
double quotient = self / other;
if (Double.IsNaN(quotient) || Double.IsInfinity(quotient) ) {
throw new FloatDomainError("NaN");
}
return InternalDivMod(self, other);
}
If the quotient is not valid then we raise a FloatDomainError. The
FloatDomainError class uses ExceptionOps.MakeMessage and also
ExceptionOps.InitializeException in the constructor. A quick look at
InitializeException puts some data into the Exception.Data property, which I am
assuming, without going any deeper, is required by the Ruby runtime to handle
the exception correctly.
This is all well and good, but when you look at BignumOps, I have a method for
to_s:
[RubyMethod("to_s")]
public static object ToString(BigInteger self, uint radix) {
try {
// TODO: Can we do the ToLower in BigInteger?
return new MutableString(self.ToString(radix).ToLower());
} catch (ArgumentOutOfRangeException x) {
throw ArgumentErrorOps.Factory(new MutableString(x.Message));
}
}
Now this one needs to raise an ArgumentError, which is actually a Ruby wrapper
around System.ArgumentException (i.e. ArgumentError is a pure Ruby class that
"extends" the CLR class System.ArgumentException. Now I could have
just created a new ArgumentException here but since this doesn''t call,
apart from anything else, ExceptionOps.InitializeException, I felt I needed to
use the ArgumentErrorOps.Factory method to create the exception. I believe the
primary reason for this method is so that the DLR can create exceptions from
pure Ruby code, i.e. raise ArgumentError, ...
Am I being over-cautious here and should I be happily creating CLR exceptions
directly and not worrying too much? I expect and hope that this is the case, as
otherwise how would the DLR deal with cases where pure .NET classes throw pure
CLR exceptions?
Cheers,
Pete
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
http://rubyforge.org/pipermail/ironruby-core/attachments/20071206/5784c170/attachment-0001.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ExceptionHierarchy.pdf
Type: application/pdf
Size: 10274 bytes
Desc: ExceptionHierarchy.pdf
Url :
http://rubyforge.org/pipermail/ironruby-core/attachments/20071206/5784c170/attachment-0001.pdf
John Lam (DLR):> I''m attaching a PDF that shows how we map CLR exceptions to Ruby > exceptions.I guess the ! means "not equivalent" and "skip parent" means we change the base class mapping but otherwise map it? (Also the bottom of the PDF appears cut off.) - John
Peter Bacon Darwin:> And to add further confusion there are also > RubyExceptions.CreateXXXError methods available. > > What to use?I think the convention is to use the RubyExceptions.CreateXXXError methods (although I''m not clear on the reason). - John
John Messerly:> Peter Bacon Darwin: > > > And to add further confusion there are also > > RubyExceptions.CreateXXXError methods available. > > > > What to use? > > I think the convention is to use the RubyExceptions.CreateXXXError > methods (although I''m not clear on the reason). >It''s so that you can think in terms of Ruby errors and not what the .NET exception type should be (IOW you don''t need to read the diagram each time). -John
Yes, use RubyExceptions where possible. Otherwise just throw corresponding BCL exception. We may enrich RubyException class with more commonly thrown exceptions. When we do so, we will search and replace affected throws across the library - that''s easy. So if you don''t find the exception that should be thrown in this class feel free to just throw the BCL exception directly. The reasons for using RubyExceptions are clarity, code reuse and consistency in error messages. RubyExceptions class should be one of the few places where Ruby to BCL exception mapping takes place - methods on RubyExceptions should be named after Ruby exception classes, so the library writer doesn''t need to think about the mapping. The class needs some refactoring though and it should probably be moved to the library. It''s on my TODO list to do so. Tomas -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of John Messerly Sent: Thursday, December 06, 2007 11:07 AM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] Raising Exceptions Peter Bacon Darwin:> And to add further confusion there are also > RubyExceptions.CreateXXXError methods available. > > What to use?I think the convention is to use the RubyExceptions.CreateXXXError methods (although I''m not clear on the reason). - John _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core
Thanks all for the clarification. Will redo the code I have been writing to use RubyExceptions where possible. Cheers, Pete -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of Tomas Matousek Sent: Thursday,06 December 06, 2007 19:31 To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] Raising Exceptions Yes, use RubyExceptions where possible. Otherwise just throw corresponding BCL exception. We may enrich RubyException class with more commonly thrown exceptions. When we do so, we will search and replace affected throws across the library - that''s easy. So if you don''t find the exception that should be thrown in this class feel free to just throw the BCL exception directly. The reasons for using RubyExceptions are clarity, code reuse and consistency in error messages. RubyExceptions class should be one of the few places where Ruby to BCL exception mapping takes place - methods on RubyExceptions should be named after Ruby exception classes, so the library writer doesn''t need to think about the mapping. The class needs some refactoring though and it should probably be moved to the library. It''s on my TODO list to do so. Tomas -----Original Message----- From: ironruby-core-bounces at rubyforge.org [mailto:ironruby-core-bounces at rubyforge.org] On Behalf Of John Messerly Sent: Thursday, December 06, 2007 11:07 AM To: ironruby-core at rubyforge.org Subject: Re: [Ironruby-core] Raising Exceptions Peter Bacon Darwin:> And to add further confusion there are also > RubyExceptions.CreateXXXError methods available. > > What to use?I think the convention is to use the RubyExceptions.CreateXXXError methods (although I''m not clear on the reason). - John _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core _______________________________________________ Ironruby-core mailing list Ironruby-core at rubyforge.org http://rubyforge.org/mailman/listinfo/ironruby-core