Dies ist eine interessante Diskussion. Ich finde das Beispiel von @ flodel ausgezeichnet. Ich denke jedoch, dass dies meinen Punkt veranschaulicht (und @koshke erwähnt dies in einem Kommentar), return
der sinnvoll ist, wenn Sie einen Imperativ anstelle eines funktionalen Codierungsstils verwenden .
Nicht um den Punkt zu belabouren, aber ich hätte so umgeschrieben foo
:
foo = function() ifelse(a,a,b)
Ein funktionaler Stil vermeidet Statusänderungen wie das Speichern des Werts von output
. In diesem Stil return
ist fehl am Platz; foo
sieht eher aus wie eine mathematische Funktion.
Ich stimme @flodel zu: Die Verwendung eines komplizierten Systems boolescher Variablen in bar
wäre weniger klar und sinnlos, wenn Sie dies getan haben return
. Was Aussagen bar
so zugänglich macht , return
ist, dass sie in einem imperativen Stil geschrieben sind. In der Tat stellen die booleschen Variablen die "Zustands" -Änderungen dar, die in einem funktionalen Stil vermieden werden.
Es ist wirklich schwierig, bar
im funktionalen Stil umzuschreiben , weil es nur ein Pseudocode ist, aber die Idee ist ungefähr so:
e_func <- function() do_stuff
d_func <- function() ifelse(any(sapply(seq(d),e_func)),2,3)
b_func <- function() {
do_stuff
ifelse(c,1,sapply(seq(b),d_func))
}
bar <- function () {
do_stuff
sapply(seq(a),b_func) # Not exactly correct, but illustrates the idea.
}
Die while
Schleife wäre am schwierigsten umzuschreiben, da sie durch Zustandsänderungen an gesteuert wird a
.
Der Geschwindigkeitsverlust, der durch einen Anruf bei verursacht wird, return
ist vernachlässigbar, aber die Effizienz, die durch das Vermeiden return
und Umschreiben in einem funktionalen Stil erzielt wird, ist oft enorm. Es return
wird wahrscheinlich nicht helfen, neuen Benutzern zu sagen, dass sie die Verwendung einstellen sollen, aber es lohnt sich, sie zu einem funktionalen Stil zu führen.
@Paul return
ist im imperativen Stil erforderlich, da Sie die Funktion häufig an verschiedenen Punkten in einer Schleife beenden möchten. Ein funktionaler Stil verwendet keine Schleifen und benötigt daher keine return
. In einem rein funktionalen Stil ist der letzte Aufruf fast immer der gewünschte Rückgabewert.
In Python erfordern Funktionen eine return
Anweisung. Wenn Sie Ihre Funktion jedoch in einem funktionalen Stil programmiert haben, haben Sie wahrscheinlich nur eine return
Anweisung: am Ende Ihrer Funktion.
Nehmen wir an einem Beispiel aus einem anderen StackOverflow-Beitrag an, wir wollten eine Funktion, die zurückgegeben wird, TRUE
wenn alle Werte in einem bestimmten Wert x
eine ungerade Länge haben. Wir könnten zwei Stile verwenden:
# Procedural / Imperative
allOdd = function(x) {
for (i in x) if (length(i) %% 2 == 0) return (FALSE)
return (TRUE)
}
# Functional
allOdd = function(x)
all(length(x) %% 2 == 1)
In einem funktionalen Stil fällt der zurückzugebende Wert natürlich an die Enden der Funktion. Wieder sieht es eher wie eine mathematische Funktion aus.
@GSee Die darin beschriebenen Warnungen ?ifelse
sind definitiv interessant, aber ich glaube nicht, dass sie versuchen, die Verwendung der Funktion zu verhindern. In der Tat ifelse
hat der Vorteil der automatischen Vektorisierung von Funktionen. Betrachten Sie beispielsweise eine leicht modifizierte Version von foo
:
foo = function(a) { # Note that it now has an argument
if(a) {
return(a)
} else {
return(b)
}
}
Diese Funktion funktioniert gut, wenn 1 length(a)
ist. Aber wenn Sie foo
mit einem neu geschrieben habenifelse
foo = function (a) ifelse(a,a,b)
Funktioniert jetzt foo
auf jeder Länge von a
. In der Tat würde es sogar funktionieren, wenn a
es sich um eine Matrix handelt. Die Rückgabe eines Werts in der gleichen Form wie test
ein Feature, das bei der Vektorisierung hilft, ist kein Problem.
return
ist auch im letzten Beispiel nicht notwendig. Das Entfernenreturn
kann es etwas schneller machen, aber meiner Ansicht nach liegt dies daran, dass R eine funktionale Programmiersprache sein soll.