Ruby é uma linguagem maravilhosa, mas tem alguns poréns. O que eu vou citar é algo bem pequeno mas a linguagem está repleta de coisas do tipo.
> class Foo > def bar; @bar; end > def bar=(other) > puts "bar= has been called" > @bar = other > end > end
Basicamente escrevemos um setter para um variável.
> foo = Foo.new > foo.bar = 1 bar= has been called => 1
Ok, exatamente como esperávamos.
> foo.bar = foo.bar || 2 bar= has been called => 1
Ok, sem surpresas ainda.
> foo.bar ||= 2 => 1
Ops, notem que bar= não foi chamado.
Portanto, ao contrário do que muitos pensam foo.bar ||= 2 é diferente de foo.bar = foo.bar || 2.
foo.bar ||= 2 só realiza a atribuição se bar não avaliar para uma expressão verdadeira.
É algo muito bobo e muito sútil, mas se o programador realizar alguma computação na atribuição, essa computação pode não ser executada em alguns casos.
Isso não é um grande problema, porém existem diversas coisas do tipo na linguagem. O Matz diz que a linguagem deve ter o comportamento que o programador espera, isso é bom porque a linguagem torna-se natural, mas e casos como esse, o que o programador espera?
Outra coisa decorrente é que isto dificulta outras implementações Ruby 100% compatíveis.