Was ist der Rückkehrpunkt in Ruby?

79

Was ist der Unterschied zwischen returneiner Variablen wie der folgenden:

keine Rückkehr

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  mood
end

Rückkehr

def write_code(number_of_errors)
  if number_of_errors > 1
    mood =  "Ask me later"
  else
    mood = puts "No Problem"
  end  
  return mood
end
thenengah
quelle

Antworten:

118

return ermöglicht es Ihnen, früh auszubrechen:

def write_code(number_of_errors)
  return "No problem" if number_of_errors == 0
  badness = compute_badness(number_of_errors)
  "WHAT?!  Badness = #{badness}."
end

Wenn number_of_errors == 0, dann "No problem"wird sofort zurückgegeben. Am Ende einer Methode ist dies jedoch nicht erforderlich, wie Sie festgestellt haben.


Bearbeiten: Um zu demonstrieren, dass das returnProgramm sofort beendet wird, betrachten Sie diese Funktion:

def last_name(name)
  return nil unless name
  name.split(/\s+/)[-1]
end

Wenn Sie diese Funktion als aufrufen last_name("Antal S-Z"), wird sie zurückgegeben "S-Z". Wenn Sie es als bezeichnen last_name(nil), wird es zurückgegeben nil. Wenn return es nicht sofort abgebrochen wird, wird versucht, es auszuführen nil.split(/\s+/)[-1], was einen Fehler auslösen würde.

Antal Spector-Zabusky
quelle
ok, gutes beispiel return speichert also den Rückgabewert, lässt aber den Rest der Methode ausführen. Ich kann es kaum erwarten, es zu benutzen.
Thenengah
4
Nein, umgekehrt: Beendet die Methode return sofort . Wenn Sie über dieses Beispiel nachdenken, wäre es nicht sinnvoll, die Schlechtigkeit zu berechnen, wenn Sie wissen, dass alles in Ordnung ist. Ich werde meine Antwort bearbeiten, um das klarer zu machen.
Antal Spector-Zabusky
8
Sie können verwendet werden return, breakusw. ohne Parameter - sie zurückkehren werden nilstandardmäßig.
Nakilon
38

Die Verwendung von "return" ist nicht erforderlich, wenn es sich um die letzte in der Methode auszuführende Zeile handelt, da Ruby automatisch den zuletzt ausgewerteten Ausdruck zurückgibt.

Sie brauchen nicht einmal diese endgültige "Stimmung", noch brauchen Sie diese Zuweisungen in der IF-Anweisung.

def write_code(number_of_errors)
    if number_of_errors > 1
       "ERROR"
    else
       "No Problem"
    end  
end

puts write_code(10)

Ausgabe:

ERROR

danneu
quelle
37
Aus einem Nicht-Ruby-Hintergrund stammend, ist diese Ausgabe definitiv WTF. :)
Patrick
return kann die Ausführung vorzeitig beenden. Es ist die Arbeit für.
Joe.wang
1
Die Rückgabe kann auch hilfreich sein, wenn eine Methode nil anstelle des zuletzt ausgewerteten Ausdrucks zurückgibt. Manchmal wird am Ende der Methoden eine Rückgabe ohne Argument angezeigt.
Garythegoat
1
@garythegoat: oder du kannst einfach schreiben nil.
Karoly Horvath
4

Ich verwende return, wenn ich eine Liste durchlaufe, und ich möchte die Funktion beenden, wenn ein Mitglied der Liste ein Kriterium erfüllt. Ich könnte dies mit einer einzigen Aussage erreichen wie:

list.select{|k| k.meets_criteria}.length == 0

in einigen Situationen aber

list.each{|k| return false if k.meets_criteria}

ist auch eine Zeile - mit meiner Meinung nach etwas mehr Flexibilität. Im ersten Beispiel wird beispielsweise davon ausgegangen, dass dies die einzige Zeile in der Methode ist und dass wir von diesem Punkt aus zurückkehren möchten, egal was passiert. Wenn dies jedoch ein Test ist, um festzustellen, ob es sicher ist, mit dem Rest der Methode fortzufahren, muss das erste Beispiel dies anders behandeln.

BEARBEITEN:

Beachten Sie die folgende Codezeile, um die Flexibilität zu erhöhen:

list_of_method_names_as_symbols.each{|k| list_of_objects.each{|j| return k if j.send(k)}}

Ich bin mir sicher, dass dies in einer Zeile ohne erreicht werden kann return, aber auf den ersten Blick sehe ich nicht, wie.

Aber dies ist jetzt eine ziemlich flexible Codezeile, die mit jeder Liste von booleschen Methoden und einer Liste von Objekten, die diese Methoden implementieren, aufgerufen werden kann.

BEARBEITEN

Es sollte beachtet werden, dass ich davon ausgehe, dass sich diese Zeile innerhalb einer Methode befindet, nicht in einem Block.


Aber dies ist meistens eine stilistische Entscheidung. Ich denke, dass Sie in den meisten Situationen die Verwendung vermeiden können und möglicherweise sollten return.

Philosodad
quelle
breakist in diesen Fällen noch nützlicher.
Nakilon
4

Ruby kehrt immer zurück! Der beste Weg ist

def write_code(number_of_errors)
  (number_of_errors > 1)? "ERROR" : "No Problem"
end

Dies bedeutet, dass wenn number_of_errors> 1 ist, ERROR zurückgegeben wird, sonst kein Problem

msroot
quelle
3

Sein netter Rubin gibt diese gute Eigenschaft, die return-Anweisung nicht explizit anzugeben, aber ich bin der Meinung, dass man als Programmierstandard immer danach streben sollte, "return" -Anweisungen anzugeben, wo immer dies erforderlich ist. Dies hilft dabei, Code für jemanden lesbarer zu machen, der aus anderen Bereichen wie C ++, Java, PHP usw. stammt und Ruby lernt. Die Anweisung "return" schadet nichts. Warum also die konventionelle und standardisiertere Methode zur Rückkehr von Funktionen überspringen?

Kush
quelle
4
„so überspringt , warum konventionelle und mehr Standardweg von Funktionen der Rückkehr“ ← weil in Ruby , Weglassen return ist der herkömmliche Standard. Wenn Sie einen returngut gestalteten Ruby-Code sehen, sollte dieser aus einem bestimmten Grund vorhanden sein, z. B. weil er früh ausbricht . Der Versuch, Konventionen für den Codestil von einer Sprache auf eine andere anzuwenden, macht es nur schwieriger, erfahrene Programmierer einzubeziehen und Ihren eigenen Codestil konsistent zu halten.
David Moles
Ich
ertappe
Ist das nicht die Nummer 2 im Zen von Ruby, "implizit ist besser als explizit"? ;-)
Mark
1

Eine kleine Warnung für diejenigen, die aus anderen Sprachen kommen. Angenommen, Sie haben eine Funktion wie die des OP und verwenden die Regel "Letzte berechnete Sache", um Ihren Rückgabewert automatisch festzulegen:

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
end

Angenommen, Sie fügen eine Debugging- (oder Protokollierungs-) Anweisung hinzu:

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  puts "### mood = #{mood}"
end

Jetzt weißt du was? Sie haben Ihren Code gebrochen, weil die putsRückgabe Null ist, was nun zum Rückgabewert der Funktion wird.

Die Lösung besteht darin, sich daran zu gewöhnen, den Rückgabewert immer explizit in die letzte Zeile zu setzen, so wie es das OP getan hat:

def write_code(number_of_errors)
  if number_of_errors > 1
     mood = "Ask me later"
  else
     mood = "No Problem"
  end  
  puts "### mood = #{mood}"
  mood
end
Tom Hundt
quelle
-1

Die Unnötigkeit returnin der letzten Zeile der Funktion ist nur syntaxischer Zucker von Ruby. In den meisten prozeduralen Sprachen müssen Sie returnin jede Funktion (in C ++ nicht ungültig) schreiben .

Nakilon
quelle
3
Ich würde es nicht als syntaktischen Zucker bezeichnen ... das Kernmerkmal hier ist, dass fast alles ein Ausdruck ist . ifAnweisungen, Anweisungsblöcke. Das ermöglicht diese Ausdruckskraft.
Karoly Horvath
Ich stimme Karoly zu - es ist kein syntaktischer Zucker, weil alles ein Ausdruck ist.
Fatuhoku