Verschachtelte Pfeilausdrücke in JavaScript (Verschachtelte Pfeilausdrücke in JavaScript), Lektion, Seite 723739
https://www.purl.org/stefan_ram/pub/verschachtelte_pfeilausdruecke_javascript (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
JavaScript-Kurs

Verschachtelte Funktionsausdrücke in JavaScript 

Lesehinweis
Die Inhalte dieser Lektion werden in den nächsten Lektionen nicht sofort wieder benötigt, sie sind aber zum Verständnis der Bedeutung von Funktionen in JavaScript  hilfreich und passen an diese Stelle des Kurses. Falls ein Leser sich aber derzeit noch nicht für die Inhalte dieser Lektion interessiert, kann er sie auch überspringen und später bei Bedarf auf sie zurückkommen.

Der Wert einer Funktion kann eine Funktion  sein.

Wir definieren zunächst eine normale Quadratfunktion.

Auswertung
quadrat = x => x * x
function quadrat()

Nun definieren wir eine weitere Funktion, deren Anwendung auf ein Argument, die Quadratfunktion ergibt.

Auswertung
f = x => quadrat
function f()

Die Anwendung der Funktion »f« auf ein Argument ergibt nun wieder die Quadratfunktion.

Auswertung
q = f( 2 )
function quadrat()

Man kann jetzt sehen, daß »q«, also die Anwendung »f( 2 )«, eine Quadratfunktion ist.

Auswertung
q( 3 )
9

Wir können »f( 2 )« auch direkt, ohne den Umweg über eine zusätzliche Funktion »q« anwenden.

Auswertung
f( 2 )( 3 )
9

Wir können »f« auch direkt als eine Funktion definieren, die eine Quadrierfunktion ergibt, ohne einen globalen Eintrag »quadrat« zu verwenden.

Auswertung
f = d => x => x * x
function f()

Die Hintereinanderschreibung zweier Pfeile ist dabei rechtsassoziativ zu verstehen, also wie in der folgenden Auswertung mit Klammern verdeutlicht wurde.

Auswertung
f = d =>( x => x * x )
function f()
Auswertung
f( 2 )( 3 )
9

Schließlich können wir eine Funktion, die ein Funktion ergibt auch ganz ohne Definition globaler Einträge auf ein Argument ausdrücken und anwenden.

Auswertung
( d => x => x * x )( 2 )( 3 )
9

Auch hier zeigen wir noch einmal die verdeutlichende Schreibweise mit Klammern.

Auswertung
( d =>( x => x * x ))( 2 )( 3 )
9

Mit den hier vorgestellten Möglichkeiten lassen sich Funktionen schreiben, die auf mehrere  Argumente angewendet werden können, beispielsweise ein Funktion zum Summieren zweier Zahlen.

Auswertung
summe =( x => y => x + y )
function summe()

Auch hier zeigen wir noch einmal die verdeutlichende Schreibweise mit Klammern.

Auswertung
summe =( x =>( y => x + y ))
function summe()
Auswertung
summe( 2 )( 3 )
5

Die Anwendung der Funktion »summe« auf das Argument »2« ergibt zunächst die Funktion »y => 2 + y«. Deren Anwendung auf das Argument »3« ergibt dann »2 + 3«, also »5«.

Auch der Aufruf  läßt sich mit zusätzlichen Klammern noch verdeutlichen. Die Anwendung  von Funktionen ist als linksassoziativ.

Auswertung
( summe( 2 ))( 3 )
5

Wegen der Polymorphie des Plusoperators »+« kann man mit der Funktion »summe« aber genausogut auch Zeichenfolgen verketten.

Auswertung
summe( "abc" )( "def" )
"abcdef"

Technisch gesehen handelt es sich bei der Funktion »summe« nicht um eine Funktion mit zwei  Parametern, sondern um eine Funktion mit einem  Parameter, die eine andere Funktion mit einem  Parameter ergibt. Wir werden etwas später sehen, wie man Funktionen ausdrücken kann, die wirklich zwei  Parameter haben.

Um eine Funktion auszudrücken, die ihr Argument um »1« erhöht, kann man nun »summe( 1 )« verwenden. Wir haben die Funktion »summe« nun „teilweise“ angewendet, also erst einmal nur auf ein  Argument – das zweite „fehlt“ noch. »summe( 1 )« bedeutet nun soviel wie »( y => 1 + y )«, dafür vergeben wir den Namen »inc«.

Auswertung
inc = summe( 1 )
function summe/<()

Durch den Aufruf der Funktion »inc« können wir nun das zweite, bisher noch „fehlende“ Argument nachliefern. »inc( 1 )« bedeutet soviel wie »( 1 + 3 )«.

Auswertung
inc( 3 )
4

Um eine Funktion auszudrücken, die ihr Argument um »1« vermindert, kann man »summe( -1 )«, also »( y => -1 + y )« verwenden.

Auswertung
dec = summe( -1 )
function summe/<()
Auswertung
dec( 3 )
2

Im folgenden Beispiel wird der Parametername »x« auch für die „innere Funktion“ verwendet. Die beiden »x« in »x + x« beziehen sich dann auf den Parameter der inneren  Funktion, weil dessen Festlegung »( x )« ihnen näher  ist.

Auswertung
( x => x => x + x )( 10 )( 2 )
4

Da die Verwendung zweier Namen mit unterschiedlicher Bedeutung in enger Nachbarschaft verwirrend sein kann, muß man sie nicht unbedingt in der Praxis einsetzen, aber es ist interessant zu wissen, daß JavaScript  sie erlaubt und versteht.

Wir zeigen noch ein anderes Beispiel mit einer Wirkfunktion.

Auswertung
f = x => ()=> console.log( x )
function f()

»f« ergibt  eine parameterlose Funktion, die das Argument von »f« ausgibt.

Wir wenden »f« auf »2« an und erhalten eine parameterlose Funktion, die »2« ausgibt.

Auswertung
p = f( 2 )
function f/<()

»p« ist nun eine parameterlose Funktion, die »2« ausgibt.

Auswertung
p()

2

undefined

Wir wenden »f« auf »abc« an und erhalten eine parameterlose Funktion, die »abc« ausgibt.

Auswertung
q = f( "abc" )
function f/<()

»q« ist nun eine parameterlose Funktion, die »abc« ausgibt.

Auswertung
q()

abc

undefined

Wir haben mit »f« also eine Funktion definiert, die Funktionen (wie »p« und »q« oben) erzeugen kann!

Bei jedem Aufruf der Funktion »f« wird dabei eine neue  Funktion erzeugt. »p« und »q« sind also zwei verschiedene Funktionen.

Jede dieser beiden Funktionen enthält einen eigenen Parameter »x«, bei »p« ist dieser gleich »2« und bei »q« ist er gleich »abc«.

Inkarnationen

Das zuletzt Beschriebene kann man mit Hilfe des Begriffs Inkarnation besser verstehen.

Zunächst wird eine parametrisierte Funktion »f« definiert.

Auswertung
f = x => ()=> console.log( x )
function f()

Bei Aufruf von »f« mit einem Argument »2« wird nun eine neue Inkarnation der Funktion »f« angelegt. Es handelt sich dabei um eine Kopie  der Funktion »f«, in welcher der Parameter den Argumentwert, also »2«, hat.

Symbolische Darstellung einer Kopie der Funktion f:
x => ()=> console.log( x )
Symbolische der Besetzung der Kopie mit der Zuordnung x=2:
()=> console.log( 2 )

Diese Kopie wurde oben als »p« bezeichnet (mit »p = f( 2 )«).

Wird nun »q = f( "abc" )« ausgewertet, so wird eine neue  Kopie von »f« mit einem neuen Parameter »x« angelegt, und in jener neuen Kopie erhält der Parameter »x« dann den Wert »"abc"«

Symbolische Darstellung einer weiteren Kopie der Funktion f:
x => ()=> console.log( x )
Symbolische der Besetzung der neuen Kopie mit der Zuordnung x=2:
()=> console.log( "abc" )

Diese neue Kopie wird dann als »q« bezeichnet (mit »q = f( 2 )«).

»p« und »q« sind also zwei unabhängige Kopien  der Funktion »f« (die sogenannten Inkarnationen), die beide einen eigenen Parameter »x« haben, der einmal »2« und einmal »"abc"« als Wert hat.

Neue Funktionen als neue Verzeichnisse

Da eine Funktion auch ein Verzeichnis ist, haben wir mit dem oben Gezeigtem gleichzeitig auch eine Möglichkeit, um bei Bedarf neue Verzeichnisse anzulegen.

Nach »p = f( 2 )« ist »p« ist ein neues Verzeichnis, wie die folgende Verwendung zeigt.

Auswertung
p.a = 28
28
Auswertung
p.a
28

Verzeichnisse werden verwendet, um zusammengehörige Daten zu speichern. So kann man beispielsweise ein neues Verzeichnis anlegen, um darin Daten zu einer Person zu sammeln. Die folgende Funktion »f« ergibt bei jedem Aufrufe eine neuen Funktion und damit ein neues Verzeichnis.

Auswertung
f = () => () => 0
function f()

Nun legen wir ein neues Verzeichnis »v« an und speichern darin Personendaten.

Auswertung
v = f()
function f/<()
Auswertung
v.vorname = "Julius"
"Julius"
Auswertung
v.nachname = "Caesar"
"Caesar"

Wir legen ein weiteres Verzeichnis »w« an und speichern darin Personendaten.

Auswertung
w = f()
function f/<()
Auswertung
w.vorname = "William"
"William"
Auswertung
w.nachname = "Shakespeare"
"Shakespeare"

Später können wir die Daten wieder auslesen.

Auswertung
v.vorname
"Julius"
Auswertung
v.nachname
"Caesar"
Auswertung
w.vorname
"William"
Auswertung
w.nachname
"Shakespeare"
Bildliche Darstellung

v w
.-------------------------. .-------------------------.
| vorname: Julius | | vorname: William |
| nachname: Caesar | | nachname: Shakespeare |
'-------------------------' '-------------------------'

Übungsfragen

?   Übungsfragen

Welche Werte haben die folgenden Ausdrücke?

Ausdruck
( x => o => x + o )( 3 )( 4 )
Ausdruck 1
( a => b => a( b ))( c => 1 + c )( 2 )
Ausdruck 2 *
( f => f( 2 )+ f( 3 ))( ( x => y => x + y )( 5 ) )

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723739 stefan_ram:723739 Verschachtelte Pfeilausdrücke in JavaScript Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723739, slrprddef723739, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/verschachtelte_pfeilausdruecke_javascript