Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specifying a default value for a setter method

Tags:

ruby

Consider the following code:

class Dummy
  def attr=(arg = 10)
    @attr = arg
  end
  def attr2=(arg = 20)
    @attr2 = 20
  end
end;
d = Dummy.new; d.attr=(); d.attr2=(); d
=> #<Dummy:0x007f8d6430e2a8 @attr=nil, @attr2=20>

It seems the attr= method discards the default parameter value and assigns nil to the instance variable anyway, yet assigning an explicit value works in the attr2= method. Why is this happening?

Edit:

I should have expressed myself in a more clear way. Assigning an explicit value obviously works in the attr2= method. That leaves only one explanation - the setter methods discard the default parameter value. Why is this discarding happening?

like image 280
Baldee Avatar asked Dec 18 '14 18:12

Baldee


1 Answers

Methods ending with = are not ordinary methods, as they are identified by ruby interpreter as setters, and hence have syntactic sugar:

d.attr = 4

When you are calling d.attr=(), you are actually calling d.attr=(()). () in ruby returns nil:

()
# => nil

Ruby interpreter will not let you get away with not having any arguments, because if you drop the () altogether, ruby will simply take the result of the next line as parameter, or throw a syntax error if you try to break the line using ;

d.attr=
  5
# => 5

d.attr=;
# => syntax error, unexpected ';'

To see your default argument at work, you can use send:

d.send(:attr=)
# => 10
d
# => #<Dummy:0x007f8d6430e2a8 @attr=10, @attr2=20>
like image 53
Uri Agassi Avatar answered Oct 15 '22 20:10

Uri Agassi