segunda-feira, 25 de julho de 2011

Pequenas coisas que incomodam em Ruby

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.