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