what's the suggested raise Exception idiom?

Discussion in 'Ruby' started by Nathan Beyer, Mar 23, 2010.

  1. Nathan Beyer

    Nathan Beyer Guest

    What's the distinction between:
    raise ArgumentError, "the argument was invalid"
    and
    raise ArgumentError.new("the argument was invalid")

    How does this apply in the case of exceptions with custom initializers
    for attributes? For example:
    class StatusCodeError < StandardError
    attr_reader :status_code
    def initialize(status_code)
    @status_code = status_code
    end
    end

    I've been reading a lot of code, books and blogs, but haven't gotten
    as clear of an understanding on why people choose one way over
    another, so I'm looking for additional opinions and commentary.

    Thanks
     
    Nathan Beyer, Mar 23, 2010
    #1
    1. Advertising

  2. On 03/23/2010 06:22 PM, Nathan Beyer wrote:
    > What's the distinction between:
    > raise ArgumentError, "the argument was invalid"
    > and
    > raise ArgumentError.new("the argument was invalid")
    >
    > How does this apply in the case of exceptions with custom initializers
    > for attributes? For example:
    > class StatusCodeError < StandardError
    > attr_reader :status_code
    > def initialize(status_code)
    > @status_code = status_code
    > end
    > end
    >
    > I've been reading a lot of code, books and blogs, but haven't gotten
    > as clear of an understanding on why people choose one way over
    > another, so I'm looking for additional opinions and commentary.


    I believe raise a,b,c,d... is merely syntactig sugar for raise
    a.new(b,c,d...) with a bit of added functionality (e.g. if a is not an
    exception class there is an error, if a is a String a StandardError is
    raised).

    To answer your question, normally there is no reason to use a variant
    with "new" - rather save yourself a bit of typing and use the shorter
    form. My 0.02EUR.

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Mar 23, 2010
    #2
    1. Advertising

  3. On Mar 23, 2010, at 2:45 PM, Robert Klemme wrote:

    > On 03/23/2010 06:22 PM, Nathan Beyer wrote:
    >> What's the distinction between:
    >> raise ArgumentError, "the argument was invalid"
    >> and
    >> raise ArgumentError.new("the argument was invalid")
    >>=20
    >> How does this apply in the case of exceptions with custom initializers
    >> for attributes? For example:
    >> class StatusCodeError < StandardError
    >> attr_reader :status_code
    >> def initialize(status_code)
    >> @status_code =3D status_code
    >> end
    >> end
    >>=20
    >> I've been reading a lot of code, books and blogs, but haven't gotten
    >> as clear of an understanding on why people choose one way over
    >> another, so I'm looking for additional opinions and commentary.

    >=20
    > I believe raise a,b,c,d... is merely syntactig sugar for raise=20
    > a.new(b,c,d...) with a bit of added functionality (e.g. if a is not an=20
    > exception class there is an error, if a is a String a StandardError is=20
    > raised).


    Not exactly so. According to the passage from RI below, "raise" with an exc=
    eption class as a first paremeter accepts up to 2 additional parameters -- =
    the first one will be used as an argument to new when the exception object =
    is instantiated, and the second, if any, must be an array representing call=
    back information.

    When I need an exception class with more than one argument, I use something=
    like the following:

    class DimensionError < RuntimeError
    attr_reader :width, :hight
    def initialize(*args)
    @width, @hight =3D *args
    super "Wrong dimension #{width}x#{hight}"
    end
    end

    begin
    raise DimensionError, [ 5, 3 ]
    rescue DimensionError =3D> error
    error.wigth
    error.length
    end

    =3D OR =3D

    class DimensionError < RuntimeError
    attr_reader :width, :hight
    def initialize(options =3D {})
    @width =3D options[:width]
    @hight =3D options[:hight]
    super "Wrong dimension #{width}x#{hight}"
    end
    end

    begin
    raise DimensionError, :width =3D> 5, :hight =3D> 3
    rescue DimensionError =3D> error
    error.wigth
    error.length
    end


    ----------------------------------------------------------- Kernel#raise
    raise
    raise(string)
    raise(exception [, string [, array]])
    fail
    fail(string)
    fail(exception [, string [, array]])
    ------------------------------------------------------------------------
    With no arguments, raises the exception in $! or raises a=20
    RuntimeError if $! is nil. With a single String argument, raises a=20
    RuntimeError with the string as a message. Otherwise, the first=20
    parameter should be the name of an Exception class (or an object=20
    that returns an Exception object when sent an exception message).=20
    The optional second parameter sets the message associated with the=20
    exception, and the third parameter is an array of callback=20
    information. Exceptions are caught by the rescue clause of=20
    begin...end blocks.

    raise "Failed to create socket"
    raise ArgumentError, "No parameters", caller
    >=20
    > To answer your question, normally there is no reason to use a variant=20
    > with "new" - rather save yourself a bit of typing and use the shorter=20
    > form. My 0.02EUR.
    >=20
    > Kind regards
    >=20
    > robert
    >=20
    > --=20
    > remember.guy do |as, often| as.you_can - without end
    > http://blog.rubybestpractices.com/
    >=20
     
    Gennady Bystritsky, Mar 24, 2010
    #3
  4. 2010/3/24 Gennady Bystritsky <>:
    >
    > On Mar 23, 2010, at 2:45 PM, Robert Klemme wrote:


    >> I believe raise a,b,c,d... is merely syntactig sugar for raise
    >> a.new(b,c,d...) with a bit of added functionality (e.g. if a is not an
    >> exception class there is an error, if a is a String a StandardError is
    >> raised).

    >
    > Not exactly so. According to the passage from RI below, "raise" with an e=

    xception class as a first paremeter accepts up to 2 additional parameters -=
    - the first one will be used as an argument to new when the exception objec=
    t is instantiated, and the second, if any, must be an array representing ca=
    llback information.

    Right you are. Thanks for the education! Apparently I never had the
    need for this. :)

    > When I need an exception class with more than one argument, I use somethi=

    ng like the following:
    >
    > class DimensionError < RuntimeError
    > =A0attr_reader :width, :hight
    > =A0def initialize(*args)
    > =A0 =A0@width, @hight =3D *args
    > =A0 =A0super "Wrong dimension #{width}x#{hight}"
    > =A0end
    > end
    >
    > begin
    > =A0raise DimensionError, [ 5, 3 ]
    > rescue DimensionError =3D> error
    > =A0error.wigth
    > =A0error.length
    > end


    That does not seem to work as you expect on 1.9:

    irb(main):038:0> class E1 < Exception
    irb(main):039:1> def initialize(*a) p a end
    irb(main):040:1> end
    =3D> nil
    irb(main):041:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    [[1, 2]]
    #<E1: E1>
    =3D> #<E1: E1>
    irb(main):042:0> class E1 < Exception
    irb(main):043:1> def initialize(*a) x,y=3D*a; p x,y end
    irb(main):044:1> end
    =3D> nil
    irb(main):045:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    [1, 2]
    nil
    #<E1: E1>
    =3D> #<E1: E1>
    irb(main):046:0> RUBY_VERSION
    =3D> "1.9.1"

    You would have to do

    irb(main):047:0> class E1 < Exception
    irb(main):048:1> def initialize(a) x,y=3D*a; p x,y end
    irb(main):049:1> end
    =3D> nil
    irb(main):050:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    1
    2
    #<E1: E1>
    =3D> #<E1: E1>
    irb(main):051:0>

    Note the missing splash operator in initialize's argument list.

    Kind regards

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Mar 24, 2010
    #4
  5. On Mar 24, 2010, at 1:31 AM, Robert Klemme wrote:

    > 2010/3/24 Gennady Bystritsky <>:
    >>=20
    >> On Mar 23, 2010, at 2:45 PM, Robert Klemme wrote:

    >=20
    >>> I believe raise a,b,c,d... is merely syntactig sugar for raise
    >>> a.new(b,c,d...) with a bit of added functionality (e.g. if a is not an
    >>> exception class there is an error, if a is a String a StandardError is
    >>> raised).

    >>=20
    >> Not exactly so. According to the passage from RI below, "raise" with an =

    exception class as a first paremeter accepts up to 2 additional parameters =
    -- the first one will be used as an argument to new when the exception obje=
    ct is instantiated, and the second, if any, must be an array representing c=
    allback information.
    >=20
    > Right you are. Thanks for the education! Apparently I never had the
    > need for this. :)
    >=20
    >> When I need an exception class with more than one argument, I use someth=

    ing like the following:
    >>=20
    >> class DimensionError < RuntimeError
    >> attr_reader :width, :hight
    >> def initialize(*args)
    >> @width, @hight =3D *args
    >> super "Wrong dimension #{width}x#{hight}"
    >> end
    >> end
    >>=20
    >> begin
    >> raise DimensionError, [ 5, 3 ]
    >> rescue DimensionError =3D> error
    >> error.wigth
    >> error.length
    >> end

    >=20
    > That does not seem to work as you expect on 1.9:
    >=20
    > irb(main):038:0> class E1 < Exception
    > irb(main):039:1> def initialize(*a) p a end
    > irb(main):040:1> end
    > =3D> nil
    > irb(main):041:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    > [[1, 2]]
    > #<E1: E1>
    > =3D> #<E1: E1>
    > irb(main):042:0> class E1 < Exception
    > irb(main):043:1> def initialize(*a) x,y=3D*a; p x,y end
    > irb(main):044:1> end
    > =3D> nil
    > irb(main):045:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    > [1, 2]
    > nil
    > #<E1: E1>
    > =3D> #<E1: E1>
    > irb(main):046:0> RUBY_VERSION
    > =3D> "1.9.1"
    >=20
    > You would have to do
    >=20
    > irb(main):047:0> class E1 < Exception
    > irb(main):048:1> def initialize(a) x,y=3D*a; p x,y end
    > irb(main):049:1> end
    > =3D> nil
    > irb(main):050:0> begin; raise E1,[1,2]; rescue Exception =3D> e; p e; end
    > 1
    > 2
    > #<E1: E1>
    > =3D> #<E1: E1>
    > irb(main):051:0>
    >=20
    > Note the missing splash operator in initialize's argument list.


    Well, I am still on 1.8.6, missed the issue on 1.9.x ;-). Thanks for pointi=
    ng this out. Besides, an exception's initialize() accepts only one paramete=
    r anyway, so your no-splash version should work for 1.8.x as well. I starte=
    d using Hash-based initialize() recently, and it seems to work same way bot=
    h in 1.8 and 1.9.

    Gennady.
     
    Gennady Bystritsky, Mar 24, 2010
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Bengt Richter
    Replies:
    0
    Views:
    364
    Bengt Richter
    Jul 7, 2005
  2. Jacol

    raise or not to raise [Newbie]

    Jacol, Feb 3, 2007, in forum: Python
    Replies:
    5
    Views:
    409
    Gabriel Genellina
    Feb 5, 2007
  3. ernest
    Replies:
    2
    Views:
    294
    Roy Smith
    Nov 14, 2010
  4. Jack Bates
    Replies:
    0
    Views:
    281
    Jack Bates
    May 2, 2011
  5. bvdp

    Raise X or Raise X()?

    bvdp, Mar 11, 2012, in forum: Python
    Replies:
    10
    Views:
    371
    Stefan Behnel
    Mar 12, 2012
Loading...

Share This Page