Hallo consuli,
ja, die Nomenklatur ist da etwas verwirrend - nicht alles, was auf Funktionen aufbaut ist auch funktional. Vielleicht hilft das Folgende bei der Einordnung: Da wir in R viele Werkzeuge einer funktionalen Sprache haben, alle Werkzeuge einer prozeduralen und viele einer objektorientierten haben, geht es in R eher um die Frage,
welchen Stil man wählt.
In der
objektorientierten Sichtweise, versucht man die Gegenstände der Welt durch Objekte abzubilden und deren Schnittstellen sehr genau zu definieren, so dass bei einem großen Software-Hersteller 100 Programmierer an 100 verschiedenen Objekten arbeiten können, ohne den Code des anderen zu kennen - jede Änderung an einem Objekt erfolgt mit einem Code, der diesem Objekt eigen ist und von ihm verantwortet wird.
Im Mittelpunkt der
funktionalen Programmierung steht nicht das Objekt, sondern die Funktion. Funktionen sind dabei möglichst einer mathematischen Funktion ähnlich. Wenn ich eine Funktion zehn mal mit denselben Argumenten aufrufe, muss zehn mal das gleiche herauskommen. Dazu führt vor allem das von jogo immer mal wieder zitierte Prinzip: "Daten gehen als Argumente in die Funktion und sie gehen als Rückgabewert aus der Funktion". Sie gehen eben nicht als globale Variable in die Funktion oder per '<<-' aus der Funktion heraus.
In C:
die '++' Anweisung nimmt die vor ihr stehende Variable und weist ihr auch gleich einen anderen Wert zu. i wird also ein Wert zugewiesen, ohne dass irgendwo expliziert 'i = ...' steht. Aber zurück zu R:
Code: Alles auswählen
# nicht 'funktional'
kundenliste <- c("Frank", "Stefan", "Gitti")
zaehleKunden <- function() length(kundenliste)
zaehleKunden()
# 'funktional'
zaehleKunden2 <- length
zaehleKunden2(kundenliste)
Eine Funktion, die nicht von globalen Variablen abhängt und deren Auswirkungen auf das Programmumfeld auf Argumente und Rückgabewert begrenzt sind, kann ich losgelöst vom sonstigen Programm betrachten, bedenken und testen und irgendwann für fehlerfrei erklären. Komischerweise stößt die funktionale Programmierung bei den einfachsten Aufgaben an Probleme: sin(x) soll für gleiche x immer denselben Wert liefern. rnorm(1) soll aber nicht jedes mal denselben Wert liefern und muss daher als Ausnahme betrachtet werden.
Ein weiteres Prinzip der funktionalen Programmierung ist das, dass Variablen möglichst nie ihren Wert ändern sollten (daher wohl die Begeisterung mancher Leute für den pipe-Operator in {magrittr}) und dass man mit Metafunktionen oft besser als mit Schleifen ausdrücken kann, was eigentlich gemeint ist.
Code: Alles auswählen
for(i in 1:100) print("R kann viele Paradigmen")
# versus
replicate(100, print("R kann viele Paradigmen"))
Die erste Zeile verwirrt mit der Erstellung eines Zahlen-Vektors und der Zuweisung zu einer Variablen i, die im Code gar nicht mehr gebraucht wird. Die zweite Zeile sagt einfach nur, was der Programmierer will.
das in Rezensionen zu funktionalen Programmierbüchern immer steht, dass es wohl eine Art Top-Down Ansatz ermöglichen soll (während die Programmlogik bei prozedural bottom-up definiert wird, richtig?).
Kann man so eine Formulierung gut oder schlecht finden. Gemeint ist wohl folgendes:
das drückt aus, dass ich etwas 100 Mal wiederholen will. Das C-Pendant dazu:
Code: Alles auswählen
int i;
for(i=0; i<100; i++) { printf("R kann viele Paradigmen"); };
Das beschreibt sehr kleinteilig, wie etwas gemacht werden soll (es soll eine Speicherzelle i geben in die ein Integer passt, diese soll auf 0 gesetzt werden, bei jedem Schleifendurchlauf um 1 erhöht werden und zwar solange i kleiner als 100 ist).
`replicate` drückt also den Gedanken des Progammierers ("Top") aus, das C-'for' geht von Speicherplätzen und deren Wertzuweisungen aus ("Bottom"). Von meinem übergeordneter Wunsch, etwas zu wiederholen, ("Top") wird bei `replicate` nicht durch Implementierungsdetails ("Bottom") abgelenkt, wie etwa der Frage, ob da intern eine Zählvariable von 0 bis 99 oder von 1 bis 100 läuft.
In R käme niemand mehr auf die Idee, C wie folgt nachzuprogrammieren. R würde es aber möglich machen:
Code: Alles auswählen
i <- 0
repeat{
print("R kann viele Paradigmen.")
i <- i + 1
if(!i<100) break
}
Das tun uns R'lern die Augen weh. Das ist so nah an der Maschine ("Bottom"), dass wir es für richtig schlechten Stil halten, auch wenn es valides R ist.
Ich weiß, das war jetzt alles schon wieder viel zu viel Text, und sollte ja eigentlich nur einen Deiner Punkte illustrieren: R ermöglicht die (unvollständige) Umsetzung vieler Programmierparadigmen und vieler Progammierstile, und wenn man sich andere Sprachen so weit anschaut, dass man versteht, welche Ideen dort wie eingesetzt werden, kann einem das zum besseren Programmierer in R machen.
Ein besserer Programmierer zu sein kann auch helfen, ein besserer Datenanalyst zu sein, auch wenn das vielleicht weder eine notwendige noch eine hinreichende Voraussetzung ist.
Ob da jetzt andere "Mainstreamsprachen" oder "akademische Sprachen" in Einzelfall nützlicher sind, kann man bestimmt nicht allgemeingültig beantworten.
LG,
Bernhard