Ruby: se variável vs se variable.nil?

11

Sou novo em Ruby e fiquei surpreso quando descobri que todos os objetos são verdadeiros, exceto nulo e falso. Mesmo 0 é verdadeiro.

Uma coisa boa sobre essa propriedade do idioma é que você pode escrever:

if !variable
  # do stuff when variable is nil
end

Meus colegas, que são desenvolvedores Ruby mais experientes, insistem que devo escolher isso em vez de usar .nil? igual a:

if variable.nil?
  # do stuff when variable is nil
end

No entanto, acredito que o último seja uma opção melhor por dois motivos: 1. Eu acho que é mais orientado a objetos, especialmente em uma linguagem como Ruby, onde tudo é um objeto e troca de mensagens. 2. É mais legível, na minha opinião, mesmo que seja menos compacto.

Estou cometendo um erro de "novato" aqui?

Javier Holguera
fonte
4
Você está testando para nada? ou um valor falso?
Estou testando para nada. Basicamente, se a variável é nulo, eu fazer algo (ou não)
Javier Holguera
3
Se você está testando para zero, por que deseja que o teste para false também insira esse bloco?
Concordo, apontei isso como outro motivo para preferir .nil? Mas eles insistiram que "se a variável fazer x" é mais do que idiomática e preferível quando você sabe que essa variável não é booleana "se variable.nil fazer x?"
Javier Holguera

Respostas:

17

Escreva o que você quer dizer. Quer dizer o que você escreve.

Vamos fazer um teste diferente. .vowel?

if char == 'a'
   # do stuff
end

vs

if char.vowel?
   # do stuff
end

Agora, é óbvio que eles não fazem a mesma coisa. Mas se você só espera charser aou bvai funcionar. Mas isso confundirá o próximo desenvolvedor - o segundo bloco será inserido para as condições em que char [eiou]também é . Mas para aisso funcionará corretamente.

Sim, é o caso nile falsesão os únicos valores falsos no Ruby. No entanto, se você está testando nil, testando para nil || false, este não é o que você quer dizer.

Isso significa que o próximo desenvolvedor (que por acaso é um assassinato louco por machado que sabe o seu endereço residencial) lerá o código e se perguntará por que falsedeveria entrar lá também.

Escreva o código que transmite exatamente o que você quer dizer.

Per Lundberg
fonte
3

Considere o seguinte:

response = responses.to_a.first

Isso retornará o primeiro elemento de responses, ou nil. Então, porque as instruções condicionais tratam nilcomo falsepodemos escrever:

response = responses.to_a.first
if response
  # do something ('happy path')
else
  # do something else
end

O que é mais legível do que:

if response.nil?
  # do something else
else
  # do something ('happy path')
end

O if (object)padrão é muito comum no código Ruby. Também leva à refatoração, por exemplo:

if response = responses.to_a.first
  do_something_with(response)
else
  # response is equal to nil
end

Lembre-se também de que um método Ruby retorna nilpor padrão. Então:

def initial_response
  if @condition
    @responses.to_a.first
  else
    nil
  end
end

pode ser simplificado para:

def initial_response
  if @condition
    @responses.to_a.first
  end
end

Para que possamos refatorar ainda mais:

if response = initial_response
  do_something_with(response)
else
  # response is equal to nil
end

Agora você pode argumentar que retornar nilnem sempre é a melhor ideia, pois significa procurar por niltodos os lugares. Mas isso é outra chaleira de peixe. Dado que testar a presença ou ausência de objetos é um requisito tão frequente, a veracidade dos objetos é um aspecto útil do Ruby, embora seja surpreendente para os novatos no idioma.

zetético
fonte
2

Não apenas é if variable.nil?mais parecido com a linguagem natural, como também protege um programador que acidentalmente atribui um falsevalor a ela e cai em sua ifdeclaração, já que Ruby é uma linguagem de tipo vagamente digitado.

Greg Burghardt
fonte
1
Então, o comentário inicial na pergunta original estava errado? Deveria ter sido "fazer coisas quando a variável for nula ou falsa"? E como o código que não corresponde ao comentário é um bug, existe um bug imediatamente?
gnasher729
Corrigir. Um teste simples de veracidade pode introduzir erros de lógica.
precisa
0

Linguisticamente, unless variableé preferível if !variable. As ifdeclarações negadas costumam ser consideradas um cheiro de código, pois é mais fácil perder a negação ao deslizar.

A imagem maior aqui é que fazer nilverificações como essa também é um pouco de cheiro de código. Para o OO adequado, tente usar o padrão de objeto nulo para que esse tipo de verificação nunca seja necessário. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Diga aos objetos o que fazer, não pergunte o que são. Isso às vezes é conhecido como dizer, não pergunte

Matt Gibson
fonte