Was macht die funktionale Programmierung aus?
Die funktionale Programmierung ist grundsätzlich deklarativ . Sie sagen, was Ihr Ergebnis ist, anstatt es zu berechnen.
Werfen wir einen Blick auf die wirklich funktionale Implementierung Ihres Snippets. In Haskell wäre es:
predsum pred numbers = sum (filter pred numbers)
Ist klar, was das Ergebnis ist? Es ist also die Summe der Zahlen, die dem Prädikat entsprechen. Wie wird es berechnet? Es ist mir egal, frag den Compiler.
Man könnte möglicherweise sagen, dass die Verwendung von sum
und filter
ein Trick ist und nicht zählt. Lassen Sie es dann ohne diese Helfer implementieren (obwohl der beste Weg wäre, sie zuerst zu implementieren).
Die "Functional Programming 101" -Lösung, die nicht verwendet wird, sum
ist mit Rekursion:
sum pred list =
case list of
[] -> 0
h:t -> if pred h then h + sum pred t
else sum pred t
Es ist immer noch ziemlich klar, was das Ergebnis in Bezug auf einen einzelnen Funktionsaufruf ist. Es ist entweder 0
oder recursive call + h or 0
abhängig davon pred h
. Immer noch ziemlich einfach, auch wenn das Endergebnis nicht sofort offensichtlich ist (obwohl dies mit ein wenig Übung wirklich wie eine for
Schleife liest ).
Vergleichen Sie das mit Ihrer Version:
public int Sum(Func<int,bool> predicate, IEnumerable<int> numbers){
int result = 0;
foreach(var item in numbers)
if (predicate(item)) result += item;
return result;
}
Was ist das Ergebnis? Oh, ich verstehe: einzelne return
Aussage, keine Überraschungen hier : return result
.
Aber was ist das result
? int result = 0
? Scheint nicht richtig. Damit machst du später etwas 0
. Ok, du fügst item
s hinzu. Und so weiter.
Für die meisten Programmierer ist dies natürlich ziemlich offensichtlich, was in einer einfachen Funktion wie dieser passiert, aber fügen Sie eine zusätzliche return
Aussage hinzu, und es wird plötzlich schwieriger zu verfolgen. Im gesamten Code geht es darum, wie und was der Leser noch herausfinden muss - dies ist eindeutig ein sehr zwingender Stil .
Sind also Variablen und Schleifen falsch?
Nein.
Es gibt viele Dinge, die durch sie viel einfacher erklärt werden, und viele Algorithmen, die einen veränderlichen Zustand erfordern, um schnell zu sein. Variablen sind jedoch von Natur aus unerlässlich. Sie erklären, wie statt was und geben nur wenige Vorhersagen darüber, wie hoch ihr Wert einige Zeilen später oder nach einigen Schleifeniterationen sein kann. Schleifen erfordern im Allgemeinen einen Zustand, um einen Sinn zu ergeben, und daher sind sie von Natur aus auch zwingend erforderlich.
Variablen und Schleifen sind einfach keine funktionale Programmierung.
Zusammenfassung
Die zeitgemäße funktionale Programmierung ist ein bisschen mehr Stil und eine nützliche Denkweise als ein Paradigma. In dieser Denkweise liegt eine starke Präferenz für die reinen Funktionen, aber es ist eigentlich nur ein kleiner Teil.
In den meisten weit verbreiteten Sprachen können Sie einige funktionale Konstrukte verwenden. In Python können Sie beispielsweise wählen zwischen:
result = 0
for num in numbers:
if pred(result):
result += num
return result
oder
return sum(filter(pred, numbers))
oder
return sum(n for n in numbers if pred(n))
Diese funktionalen Ausdrücke passen gut zu solchen Problemen und machen den Code einfach kürzer (und kürzer ist gut ). Sie sollten imperativen Code nicht gedankenlos durch sie ersetzen, aber wenn sie passen, sind sie fast immer die bessere Wahl.
item
Variable in der Schleife mutiert.