Ruby: if variable vs if variable.nil?

11

Je suis nouveau chez Ruby et j'ai été surpris quand j'ai découvert que tous les objets étaient vrais, à part zéro et faux. Même 0 est vrai.

Une bonne chose à propos de cette propriété de la langue est que vous pouvez écrire:

if !variable
  # do stuff when variable is nil
end

Mes collègues, qui sont des développeurs Ruby plus aguerris, insistent pour que je choisisse cela au lieu d'utiliser .nil? ainsi:

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

Cependant, je pense que ce dernier est une meilleure option pour deux raisons: 1. Je pense qu'il est plus orienté objet, en particulier dans un langage comme Ruby où tout est un échange d'objet et de message. 2. Il est plus lisible, à mon avis, même s'il est moins compact.

Suis-je en train de faire une erreur de "débutant" ici?

Javier Holguera
la source
4
Testez-vous pour zéro? ou une fausse valeur?
Je teste pour rien. Fondamentalement, si la variable est nulle, je fais quelque chose (ou pas)
Javier Holguera
3
Si vous testez pour zéro, pourquoi voulez-vous que le test pour faux entre également dans ce bloc?
D'accord, j'ai souligné cela comme une autre raison de préférer .nil? Mais ils ont insisté sur le fait que "si variable do x" est plus idiomatique que "si variable.nil? Do x" et préférable quand vous savez que cette variable n'est pas booléenne
Javier Holguera

Réponses:

17

Écrivez ce que vous voulez dire. Faites ce que vous écrivez.

Prenons un test différent. .vowel?

if char == 'a'
   # do stuff
end

contre

if char.vowel?
   # do stuff
end

Maintenant, il est évident que ceux-ci ne font pas la même chose. Mais si vous vous attendez charà ce que ce soit aou bcela fonctionnera. Mais cela confondra le prochain développeur - le deuxième bloc sera saisi pour les conditions où char est [eiou]également. Mais pour a, cela fonctionnera correctement.

Oui, c'est le cas nilet ce falsesont les seules valeurs de falsification dans Ruby. Cependant, si vous testez nilen testant nil || false, ce n'est pas ce que vous voulez dire.

Cela signifie que le prochain développeur (qui se trouve être un assassin fou de hache qui connaît votre adresse personnelle) lira le code et se demandera pourquoi falsedevrait également y entrer.

Écrivez le code qui transmet exactement ce que vous voulez dire.

Per Lundberg
la source
3

Considérer ce qui suit:

response = responses.to_a.first

Cela renverra le premier élément de responses, ou nil. Ensuite, parce que les instructions conditionnelles traitent ce nilque falsenous pouvons écrire:

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

Ce qui est plus lisible que:

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

Le if (object)modèle est très courant dans le code Ruby. Cela conduit également très bien à la refactorisation, par exemple:

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

Souvenez-vous également qu'une méthode Ruby renvoie nilpar défaut. Donc:

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

peut être simplifié pour:

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

Nous pouvons donc refactoriser davantage:

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

Vous pouvez maintenant affirmer que le retour niln'est pas toujours la meilleure idée, car cela signifie vérifier nilpartout. Mais c'est une autre marmite de poisson. Étant donné que les tests de présence ou d'absence d'un objet sont une exigence si fréquente, la véracité des objets est un aspect utile de Ruby, bien que surprenant pour les nouveaux arrivants dans le langage.

zététique
la source
2

Non seulement est if variable.nil?lu plus comme un langage naturel, il protège également contre un programmeur qui lui attribue accidentellement une falsevaleur et tombe dans votre ifdéclaration, car Ruby est un langage vaguement tapé.

Greg Burghardt
la source
1
Donc, le commentaire initial dans la question d'origine était faux? Aurait dû être "faire des choses quand la variable est nulle ou fausse"? Et comme le code ne correspondant pas au commentaire est un bug, y a-t-il un bug tout de suite?
gnasher729
Correct. Un simple test de véracité pourrait introduire des erreurs logiques.
Greg Burghardt
0

Idiomatiquement, unless variableest préférable à if !variable. Les ifdéclarations négatives sont souvent considérées comme une odeur de code car il est plus facile de manquer la négation lors de l'écrémage.

La vue d'ensemble ici est que faire des nilvérifications comme celle-ci est aussi une odeur de code. Pour un bon OO, essayez d'utiliser le modèle d'objet nul afin que ce type de vérification ne soit jamais nécessaire. http://devblog.avdi.org/2011/05/05/30/null-objects-and-falsiness/

Dites aux objets quoi faire, ne leur demandez pas ce qu'ils sont. Ceci est parfois connu sous le nom de ne pas demander

Matt Gibson
la source