Ruby: if variable vs if variable.nil?

11

Ich bin neu bei Ruby und war überrascht, als ich herausfand, dass alle Objekte außer Null und Falsch wahr sind. Sogar 0 ist wahr.

Eine schöne Sache an dieser Eigenschaft der Sprache ist, dass Sie schreiben können:

if !variable
  # do stuff when variable is nil
end

Meine Kollegen, die erfahrenere Ruby-Entwickler sind, bestehen darauf, dass ich das wählen sollte, anstatt .nil? wie so:

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

Ich glaube jedoch, dass Letzteres aus zwei Gründen eine bessere Option ist: 1. Ich denke, es ist objektorientierter, insbesondere in einer Sprache wie Ruby, in der alles ein Objekt- und Nachrichtenaustausch ist. 2. Es ist meiner Meinung nach besser lesbar, auch wenn es weniger kompakt ist.

Mache ich hier einen "Neuling" -Fehler?

Javier Holguera
quelle
4
Testen Sie auf Null? oder ein falscher Wert?
Ich teste auf Null. Grundsätzlich, wenn die Variable Null ist, mache ich etwas (oder nicht)
Javier Holguera
3
Wenn Sie auf Null testen, warum soll der Test auf Falsch auch in diesen Block eingegeben werden?
Ich stimme zu, ich habe darauf hingewiesen, dass dies ein weiterer Grund ist, .nil? Aber sie bestanden darauf, dass "wenn Variable do x" idiomatischer ist als "wenn Variable.nil? Do x" und vorzuziehen, wenn Sie wissen, dass Variable nicht boolesch ist
Javier Holguera

Antworten:

17

Schreiben Sie, was Sie meinen. Meinen Sie, was Sie schreiben.

Machen wir einen anderen Test. .vowel?

if char == 'a'
   # do stuff
end

vs.

if char.vowel?
   # do stuff
end

Nun ist es offensichtlich, dass diese nicht dasselbe tun. Aber wenn Sie erwarten , nur charsein , aoder bes wird funktionieren. Aber es wird den nächsten Entwickler verwirren - der zweite Block wird für die Bedingungen eingegeben, unter denen auch char ist [eiou]. Aber dafür awird es richtig funktionieren.

Ja, das ist der Fall nilund falsesind die einzigen falschen Werte in Ruby. Wenn Sie jedoch testen, nilindem Sie testen nil || false, ist dies nicht das, was Sie meinen.

Dies bedeutet, dass der nächste Entwickler (der zufällig ein verrückter Axtmord ist, der Ihre Privatadresse kennt) den Code liest und sich fragt, warum er auch falsedort hineingehen sollte.

Schreiben Sie den Code, der genau das vermittelt , was Sie meinen.

Per Lundberg
quelle
3

Folgendes berücksichtigen:

response = responses.to_a.first

Dies gibt das erste Element von responsesoder zurück nil. Dann, weil bedingte Anweisungen so behandeln, nilwie falsewir schreiben können:

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

Welches ist besser lesbar als:

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

Das if (object)Muster ist im Ruby-Code sehr verbreitet. Es führt auch gut zum Refactoring, zB:

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

Denken Sie auch daran, dass eine Ruby-Methode nilstandardmäßig zurückgegeben wird. So:

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

kann vereinfacht werden zu:

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

So können wir weiter überarbeiten:

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

Jetzt können Sie argumentieren, dass eine Rückkehr nilnicht immer die beste Idee ist, da dies bedeutet, dass Sie nilüberall nachsehen müssen. Aber das ist noch ein Fischkessel. Angesichts der Tatsache, dass das Testen auf "Anwesenheit oder Abwesenheit" von Objekten eine so häufige Anforderung ist, ist die Wahrhaftigkeit von Objekten ein nützlicher Aspekt von Ruby, wenn auch überraschend für Neulinge in der Sprache.

zetetisch
quelle
2

Es wird nicht nur if variable.nil?eher wie eine natürliche Sprache gelesen, sondern es wird auch verhindert, dass ein Programmierer ihm versehentlich einen falseWert zuweist und in Ihre ifAussage fällt, da Ruby eine lose typisierte Sprache ist.

Greg Burghardt
quelle
1
Der erste Kommentar in der ursprünglichen Frage war also falsch? Sollte "Sachen machen, wenn die Variable null oder falsch ist" gewesen sein? Und da Code, der nicht mit dem Kommentar übereinstimmt, ein Fehler ist, gibt es sofort einen Fehler?
Gnasher729
Richtig. Ein einfacher Wahrheitstest kann zu logischen Fehlern führen.
Greg Burghardt
0

Idiomatisch unless variableist vorzuziehen if !variable. Negierte ifAnweisungen werden oft als Codegeruch angesehen, da es einfacher ist, die Negation beim Überfliegen zu übersehen.

Das größere Bild hier ist, dass solche nilÜberprüfungen auch ein bisschen nach Code riechen. Verwenden Sie für eine ordnungsgemäße OO das Nullobjektmuster, damit diese Art der Überprüfung niemals erforderlich ist. http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/

Sagen Sie den Objekten, was zu tun ist, und fragen Sie sie nicht, was sie sind. Dies wird manchmal als Tell Don't Ask bezeichnet

Matt Gibson
quelle