Assert_raise question

def test_raise
  assert_raise ArgumentError {raise ArgumentError.new("basic argument issue")}
end

Now there's suddenly an Exception: undefined method 'ArgumentError'...
I was more than a little surprised to discover that the parens make a
difference here? Can anyone explain to me _why_ there's a difference?

I believe that x y z is parsed as x(y(z)):

  irb(main):013:0> puts ArgumentError
  ArgumentError
  => nil
  irb(main):014:0> puts ArgumentError 123
  (irb):14: warning: parenthesize argument(s) for future version
  NoMethodError: undefined method `ArgumentError' for main:Object
          from (irb):14
  irb(main):015:0> puts ArgumentError(123)
  NoMethodError: undefined method `ArgumentError' for main:Object
          from (irb):15
  irb(main):016:0>

and x y {block} is parsed as x(y() {block}), i.e. y is forced to be a method
call as that's the only meaningful thing next to a block.

  irb(main):017:0> def Wibble(*args,&blk)
  irb(main):018:1> puts "Args: #{args.inspect}"
  irb(main):019:1> puts "With block" if blk
  irb(main):020:1> end
  => nil
  irb(main):021:0> puts Wibble { raise "hello" }
  Args:
  With block
  nil
  => nil
  irb(main):022:0> puts Wibble Wibble { raise "hello" }
  (irb):22: warning: parenthesize argument(s) for future version
  Args:
  With block
  Args: [nil]
  nil
  => nil

There's also the ambiguity between hash literal and block to consider:

  irb(main):027:0> puts { :one => 2 }
  SyntaxError: compile error
  (irb):27: parse error, unexpected tASSOC, expecting '}'
  puts { :one => 2 }
                ^
          from (irb):27
  irb(main):028:0> puts({ :one => 2 })
  one2
  => nil
  irb(main):029:0> puts 123, { :one => 2 }
  123
  one2
  => nil
  irb(main):030:0> puts { raise }
  
  => nil
  irb(main):031:0> puts :one => 2
  one2
  => nil

B.

···

from :0
          from :0
          from :0

Brian Candler wrote:

def test_raise
  assert_raise ArgumentError {raise ArgumentError.new("basic argument issue")}
end

Now there's suddenly an Exception: undefined method 'ArgumentError'...
I was more than a little surprised to discover that the parens make a
difference here? Can anyone explain to me _why_ there's a difference?

I believe that x y z is parsed as x(y(z)):

  irb(main):013:0> puts ArgumentError
  ArgumentError
  => nil
  irb(main):014:0> puts ArgumentError 123
  (irb):14: warning: parenthesize argument(s) for future version
  NoMethodError: undefined method `ArgumentError' for main:Object
          from (irb):14
          from :0
  irb(main):015:0> puts ArgumentError(123)
  NoMethodError: undefined method `ArgumentError' for main:Object
          from (irb):15
          from :0
  irb(main):016:0>

and x y {block} is parsed as x(y() {block}), i.e. y is forced to be a
method
call as that's the only meaningful thing next to a block.

[snip]

Well, now that you explained it, it makes perfect sense! Thanks.

I guess in the future I'll double-check a little more carefully that my
code is doing what I expect when I leave out parens.

Doug

···

--
Posted via http://www.ruby-forum.com/\.