4 Stimmen

Sollte ich Rückgaben in mehrzeiligen Scala-Methoden verwenden?

Vielleicht liegt es nur an meinem Hintergrund in der eher imperativen Programmierung, aber ich habe gerne Return-Anweisungen in meinem Code.

Ich weiß, dass in Scala in vielen Methoden keine Rückgaben erforderlich sind, da der zuletzt berechnete Wert standardmäßig zurückgegeben wird. Ich verstehe, dass dies für einen "Einzeiler" durchaus Sinn macht, z.B.

def square(x) = x * x

Ich verstehe auch den endgültigen Grund für die Verwendung expliziter Rückgaben (wenn Sie mehrere Verzweigungen haben, die Ihr Code annehmen könnte, und Sie die Methode für verschiedene Verzweigungen verlassen wollen, z. B. wenn ein Fehler auftritt). Aber was ist mit mehrzeiligen Funktionen? Wäre es nicht lesbarer und sinnvoller, wenn es eine explizite Rückgabe gäbe, z. B.

def average(x: List[Int]) : Float = {
  var sum = 0
  x.foreach(sum += _)
  return sum / x.length.toFloat
}

11voto

IttayD Punkte 26802
def average(x: List[Int]) : Float = 
  x.foldLeft(0)(_ + _) / x.length.toFloat

UPDATE: Ich wollte zeigen, wie ein iterativer Code in einen funktionalen Ausdruck umgewandelt werden kann, aber @soc hat zu Recht bemerkt, dass es eine noch kürzere Version gibt x.sum / x.length.toFloat

Ich finde, dass ich in Scala in der Regel weniger Bedarf habe, "in der Mitte zurückzukehren". Außerdem wird eine große Funktion in kleinere Ausdrücke unterteilt, die sich besser erklären lassen. Anstelle von

var x = ...
if (some condition) x = ...
else x = ...

I if (eine Bedingung) ... sonst ....

Ähnlich verhält es sich mit Match-Ausdrücken. Und Sie können immer verschachtelte Hilfsklassen haben.

Wenn Sie sich mit vielen Formen von Ausdrücken vertraut gemacht haben, die zu einem Ergebnis führen (z. B. "if"), ohne eine Rückgabeanweisung zu haben, dann wirkt eine solche in Ihren Methoden fehl am Platz.

An einem Arbeitsplatz gab es eine Regel, die besagte, dass "return" nicht in der Mitte einer Methode stehen darf, da es für einen Leser des Codes leicht zu übersehen ist. Wenn "return" nur in der letzten Zeile steht, wozu ist es dann überhaupt gut?

10voto

Rex Kerr Punkte 164629

En return sagt einem nichts Zusätzliches, so dass ich finde, dass es mein Verständnis der Vorgänge eher erschwert. Von Kurs es kehrt zurück; es gibt keine weiteren Anweisungen!

Und es ist auch eine gute Idee, sich die Gewohnheit abzugewöhnen, die return denn es ist wirklich unklar, wohin Sie zurückkehren a wenn Sie stark funktionalen Code verwenden:

def manyFutures = xs.map(x => Futures.future { if (x<5) return Nil else x :: Nil })

Wohin soll die Rückkehr die Ausführung führen? Außerhalb von manyFutures ? Nur der innere Block?

Obwohl Sie also explizite Rückgaben verwenden können (zumindest, wenn Sie den Rückgabetyp explizit angeben), schlage ich vor, dass Sie sich stattdessen an die Gewohnheit des letzten Satzes-ist-der-Rückgabewert gewöhnen.

3voto

Aaron Novstrup Punkte 20687

Ihr Gefühl, dass die Version mit dem return besser lesbar ist, ist wahrscheinlich ein Zeichen dafür, dass Sie immer noch denken unbedingt statt deklaratorisch . Versuchen Sie, Ihre Funktion aus der Perspektive zu betrachten, was sie ist (d. h. wie sie definiert ist), sondern was sie tut (d. h. wie sie berechnet wird).

Schauen wir uns Ihre average Beispiel, und tun Sie so, als ob die Standardbibliothek nicht über die Funktionen verfügt, die einen eleganten Einzeiler möglich machen. Im Englischen würden wir sagen, dass der Durchschnitt einer Liste von Zahlen die Summe der Zahlen in der Liste geteilt durch ihre Länge ist.

def average(xs: List[Int]): Float = {
   var sum = 0
   xs.foreach(sum += _)
   sum / xs.length.toFloat
}

Diese Beschreibung entspricht ziemlich genau der englischen Version, wobei die ersten beiden Zeilen der Funktion nicht berücksichtigt wurden. Wir können den Faktor sum Funktion, um eine deklarativere Beschreibung zu erhalten:

def average(xs: List[Int]): Float = {
   def sum(xs: List[Int]): Int = // ...
   sum(xs) / xs.length.toFloat
}

In der deklarativen Definition ist eine return Aussage liest sich ziemlich unnatürlich, weil sie den Schwerpunkt ausdrücklich auf bei etwas.

2voto

kiritsuku Punkte 52437

Ich vermisse die Return-Anweisung am Ende einer Methode nicht, weil sie unnötig ist. Außerdem gibt in Scala jede Methode einen Wert zurück - auch Methoden, die nichts zurückgeben sollten. Anstelle von void gibt es den Typ Unit die zurückgegeben wird:

def x { println("hello") }

kann geschrieben werden als:

def x { println("hello"); return Unit }

Aber println gibt bereits den Typ Unit zurück - wenn Sie also explizit eine return-Anweisung verwenden wollen, müssen Sie sie in Methoden verwenden, die Unit auch. Andernfalls haben Sie keinen durchgängig identischen Build-on-Code.

Aber in Scala gibt es die Möglichkeit, Ihren Code in vielen kleinen Methoden zu brechen:

def x(...): ReturnType = {
  def func1 = ... // use funcX
  def func2 = ... // use funcX
  def func3 = ... // use funcX
  funcX
}

Eine explizit verwendete Rückgabeanweisung trägt nicht zum besseren Verständnis des Codes bei.

Außerdem verfügt Scala über eine leistungsfähige Kernbibliothek, mit der man viele Probleme mit weniger Code lösen kann:

def average(x: List[Int]): Float = x.sum.toFloat / x.length

0voto

hbatista Punkte 1207

Ich glaube, Sie sollten nicht return Ich denke, es widerspricht irgendwie dem eleganten Konzept, dass in Scala alles ein Ausdruck ist, der zu etwas ausgewertet wird.

Wie Ihr average Methode: Es ist einfach ein Ausdruck, der zu Float Sie müssen nichts zurückgeben, damit das funktioniert.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X