Anonyme Funktion – Wikipedia

Funktionsdefinition, die nicht an einen Bezeichner gebunden ist

In der Computerprogrammierung wird ein anonyme Funktion ((Funktionsliteral, Lambda-Abstraktion, oder Lambda-Ausdruck) ist eine Funktionsdefinition, die nicht an einen Bezeichner gebunden ist. Anonyme Funktionen sind häufig Argumente, die an Funktionen höherer Ordnung übergeben oder zum Erstellen des Ergebnisses einer Funktion höherer Ordnung verwendet werden, die eine Funktion zurückgeben muss.[1]

Wenn die Funktion nur einmal oder eine begrenzte Anzahl von Malen verwendet wird, ist eine anonyme Funktion möglicherweise syntaktisch leichter als die Verwendung einer benannten Funktion. Anonyme Funktionen sind in funktionalen Programmiersprachen und anderen Sprachen mit erstklassigen Funktionen allgegenwärtig, wo sie für den Funktionstyp dieselbe Rolle erfüllen wie Literale für andere Datentypen.

Anonyme Funktionen stammen aus der Arbeit der Alonzo-Kirche in seiner Erfindung des Lambda-Kalküls, in dem alle Funktionen 1936 vor elektronischen Computern anonym sind.[2] In mehreren Programmiersprachen werden anonyme Funktionen mit dem Schlüsselwort eingeführt Lambdaund anonyme Funktionen werden oft als Lambdas oder Lambda-Abstraktionen bezeichnet. Anonyme Funktionen sind seit Lisp im Jahr 1958 ein Merkmal von Programmiersprachen, und eine wachsende Anzahl moderner Programmiersprachen unterstützt anonyme Funktionen.

Anonyme Funktionen können verwendet werden, um Funktionen zu enthalten, die nicht benannt werden müssen, und möglicherweise für die kurzfristige Verwendung. Einige bemerkenswerte Beispiele sind Verschlüsse und Curry.

Die Verwendung anonymer Funktionen ist eine Frage des Stils. Ihre Verwendung ist niemals der einzige Weg, um ein Problem zu lösen. Jede anonyme Funktion könnte stattdessen als benannte Funktion definiert und beim Namen aufgerufen werden. Einige Programmierer verwenden anonyme Funktionen, um bestimmten, nicht wiederverwendbaren Code zu kapseln, ohne den Code mit vielen kleinen einzeiligen normalen Funktionen zu verunreinigen.

In einigen Programmiersprachen werden anonyme Funktionen üblicherweise für ganz bestimmte Zwecke implementiert, z. B. zum Binden von Ereignissen an Rückrufe oder zum Instanziieren der Funktion für bestimmte Werte, die effizienter, lesbarer und weniger fehleranfällig sein können als das Aufrufen eines allgemeineren Namens Funktion.

Die folgenden Beispiele sind in Python 3 geschrieben.

Sortierung[edit]

Wenn Sie versuchen, nicht standardmäßig zu sortieren, ist es möglicherweise einfacher, die Sortierlogik als anonyme Funktion zu enthalten, als eine benannte Funktion zu erstellen. Die meisten Sprachen bieten eine generische Sortierfunktion, die einen Sortieralgorithmus implementiert, der beliebige Objekte sortiert. Diese Funktion akzeptiert normalerweise eine beliebige Funktion, die bestimmt, wie zu vergleichen ist, ob zwei Elemente gleich sind oder ob eines größer oder kleiner als das andere ist.

Betrachten Sie diesen Python-Code, der eine Liste von Zeichenfolgen nach Länge der Zeichenfolge sortiert:

>>> a = ['house', 'car', 'bike']
>>> a.sort(key=lambda x: len(x))
>>> print(a)
['car', 'bike', 'house']

Die anonyme Funktion in diesem Beispiel ist der Lambda-Ausdruck:

Grundlegende Syntax einer Lambda-Funktion in Python ist

lambda arg1, arg2, arg3, ...: <operation on the arguments returning a value>

Der von der Lambda-Funktion zurückgegebene Ausdruck kann einer Variablen zugewiesen und an mehreren Stellen im Code verwendet werden.

>>> add = lambda a: a + a
>>> print(add(20))
40

Die anonyme Funktion akzeptiert ein Argument: xund gibt die Länge seines Arguments zurück, das dann von der verwendet wird sort() Methode als Kriterium für die Sortierung. Ein anderes Beispiel wäre das Sortieren von Elementen in einer Liste nach dem Namen ihrer Klasse (in Python hat alles eine Klasse):

>>> a = [10, 'number', 11.2]
>>> a.sort(key=lambda x: x.__class__.__name__)
>>> print(a)
[11.2, 10, 'number']

Beachten Sie, dass 11.2 hat Klassennamen “float“, 10 hat Klassennamen “int“, und 'number' hat Klassennamen “str“. Die sortierte Reihenfolge ist”float“,”int“, dann “str“.

Verschlüsse[edit]

Abschlüsse sind Funktionen, die in einer Umgebung ausgewertet werden, die gebundene Variablen enthält. Im folgenden Beispiel wird die Variable “Schwelle” in einer anonymen Funktion gebunden, die die Eingabe mit der Schwelle vergleicht.

def comp(threshold):
    return lambda x: x < threshold

Dies kann als eine Art Generator für Vergleichsfunktionen verwendet werden:

>>> func_a = comp(10)
>>> func_b = comp(20)

>>> print(func_a(5), func_a(8), func_a(13), func_a(21))
True True False False

>>> print(func_b(5), func_b(8), func_b(13), func_b(21))
True True True False

Es wäre unpraktisch, für jede mögliche Vergleichsfunktion eine Funktion zu erstellen, und es könnte zu unpraktisch sein, den Schwellenwert für die weitere Verwendung beizubehalten. Unabhängig vom Grund, warum ein Abschluss verwendet wird, ist die anonyme Funktion die Entität, die die Funktionalität enthält, die den Vergleich durchführt.

Currying[edit]

Beim Currying wird eine Funktion so geändert, dass nicht mehrere Eingaben, sondern eine einzelne Eingabe und eine Funktion zurückgegeben werden, die die zweite Eingabe akzeptiert, und so weiter. In diesem Beispiel wird eine Funktion, die eine Division durch eine beliebige Ganzzahl ausführt, in eine Funktion umgewandelt, die eine Division durch eine festgelegte Ganzzahl ausführt.

>>> def divide(x, y):
...     return x / y

>>> def divisor(d):
...     return lambda x: divide(x, d)

>>> half = divisor(2)
>>> third = divisor(3)

>>> print(half(32), third(32))
16.0 10.666666666666666

>>> print(half(40), third(40))
20.0 13.333333333333334

Während die Verwendung anonymer Funktionen beim Currying möglicherweise nicht üblich ist, kann sie dennoch verwendet werden. Im obigen Beispiel generiert der Funktionsteiler Funktionen mit einem angegebenen Teiler. Die Funktionen halb und drittens curry die Divisionsfunktion mit einem festen Divisor.

Die Divisorfunktion bildet auch einen Abschluss durch Binden der Variablen d.

Funktionen höherer Ordnung[edit]

Eine Funktion höherer Ordnung ist eine Funktion, die eine Funktion als Argument verwendet. Dies wird häufig verwendet, um das Verhalten einer generisch definierten Funktion anzupassen, häufig eines Schleifenkonstrukts oder eines Rekursionsschemas. Anonyme Funktionen sind eine bequeme Möglichkeit, solche Funktionsargumente anzugeben. Die folgenden Beispiele befinden sich in Python 3.

Karte[edit]

Die Kartenfunktion führt einen Funktionsaufruf für jedes Element einer Liste aus. Im folgenden Beispiel wird jedes Element in einem Array mit einer anonymen Funktion quadriert.

>>> a = [1, 2, 3, 4, 5, 6]
>>> print(list(map(lambda x: x*x, a)))
[1, 4, 9, 16, 25, 36]

Die anonyme Funktion akzeptiert ein Argument und multipliziert es mit sich selbst (quadriert es). Die obige Form wird von den Schöpfern der Sprache entmutigt, die behaupten, dass die unten dargestellte Form dieselbe Bedeutung hat und eher mit der Philosophie der Sprache übereinstimmt:

>>> a = [1, 2, 3, 4, 5, 6]
>>> print([x*x for x in a])
[1, 4, 9, 16, 25, 36]

Filter[edit]

Die Filterfunktion gibt alle Elemente aus einer Liste zurück, die True auswerten, wenn sie an eine bestimmte Funktion übergeben werden.

>>> a = [1, 2, 3, 4, 5, 6]
>>> print(list(filter(lambda x: x % 2 == 0, a)))
[2, 4, 6]

Die anonyme Funktion prüft, ob das an sie übergebene Argument gerade ist. Das gleiche wie bei der folgenden Kartenform wird als angemessener angesehen:

>>> a = [1, 2, 3, 4, 5, 6]
>>> print([x for x in a if x % 2 == 0])
[2, 4, 6]

Falten[edit]

Eine Faltfunktion läuft über alle Elemente in einer Struktur (für Listen, die normalerweise von links nach rechts sind, wird eine “linke Faltung” aufgerufen reduce in Python), indem ein Wert akkumuliert wird. Dies kann verwendet werden, um alle Elemente einer Struktur zu einem Wert zu kombinieren, zum Beispiel:

>>> from functools import reduce
>>> a = [1, 2, 3, 4, 5]
>>> print(reduce(lambda x,y: x*y, a))
120

Dies führt durch

((((((1×2)×3)×4)×5=120.{ displaystyle left ( left ( left (1 times 2 right) times 3 right) times 4 right) times 5 = 120.}

Die anonyme Funktion ist hier die Multiplikation der beiden Argumente.

Das Ergebnis einer Falte muss nicht ein Wert sein. Stattdessen können sowohl Karte als auch Filter mithilfe von Falz erstellt werden. In Map ist der akkumulierte Wert eine neue Liste, die die Ergebnisse der Anwendung einer Funktion auf jedes Element der ursprünglichen Liste enthält. Im Filter ist der akkumulierte Wert eine neue Liste, die nur die Elemente enthält, die der angegebenen Bedingung entsprechen.

Liste der Sprachen[edit]

Das Folgende ist eine Liste von Programmiersprachen, die unbenannte anonyme Funktionen vollständig oder teilweise als eine Variante oder überhaupt nicht unterstützen.

Diese Tabelle zeigt einige allgemeine Trends. Erstens sind die Sprachen, die keine anonymen Funktionen unterstützen (C, Pascal, Object Pascal), alle statisch typisierte Sprachen. Statisch typisierte Sprachen können jedoch anonyme Funktionen unterstützen. Zum Beispiel sind die ML-Sprachen statisch typisiert und enthalten grundsätzlich anonyme Funktionen, und Delphi, ein Dialekt von Object Pascal, wurde erweitert, um anonyme Funktionen zu unterstützen, ebenso wie C ++ (nach dem C ++ 11-Standard). Zweitens haben die Sprachen, die Funktionen als erstklassige Funktionen behandeln (Dylan, Haskell, JavaScript, Lisp, ML, Perl, Python, Ruby, Schema), im Allgemeinen eine anonyme Funktionsunterstützung, sodass Funktionen genauso einfach definiert und weitergegeben werden können wie andere Daten Typen.

Sprache Unterstützung Anmerkungen
ActionScript Y.
Ada N. Ausdrucksfunktionen sind Teil von Ada2012
ALGOL 68 Y.
APL Y. Dyalog, ngn und dzaima APL unterstützen sowohl dfns- als auch implizite Funktionen vollständig. GNU APL unterstützt dfns nur eingeschränkt.
Assemblersprachen N.
Bash Y. Es wurde eine Bibliothek erstellt, die anonyme Funktionen in Bash unterstützt.[3]
C. N. Unterstützung wird in Clang und zusammen mit dem LLVM-Compiler-rt lib bereitgestellt. GCC-Unterstützung wird für eine Makroimplementierung gegeben, die die Möglichkeit der Verwendung ermöglicht. Siehe unten für weitere Details.
C # Y. [4]
C ++ Y. Ab dem C ++ 11 Standard
CFML Y. Ab Railo 4,[5]ColdFusion 10[6]
Clojure Y.
COBOL N. Der nicht standardmäßige Managed COBOL-Dialekt von Micro Focus unterstützt Lambdas, die als anonyme Delegaten / Methoden bezeichnet werden.[7]
Curl Y.
D. Y.
Pfeil Y. [8]
Delphi Y. [9]
Dylan Y.
Eiffel Y.
Ulme Y.
Elixier Y. [10]
Erlang Y. [11]
F # Y. [12]
Faktor Y. “Zitate” unterstützen dies[13]
Fortran N.
Frink Y. [14]
Gehen Y. [15]
Gosu Y. [16]
Groovy Y. [17]
Haskell Y.
Haxe Y.
Java Y. Unterstützt in Java 8. Weitere Informationen finden Sie im Abschnitt zu Java-Einschränkungen.
JavaScript Y.
Julia Y. [18]
Kotlin Y. [19]
Lispeln Y.
Logtalk Y.
Lua Y. [20]
MUMPS N.
Mathematica Y.
Ahorn Y. [21]
MATLAB Y.
Maxima Y. [22]
Shell der nächsten Generation Y.
Nim Y. [23]
OCaml Y. [24]
Oktave Y. [25]
Objekt Pascal Y. Delphi, ein Dialekt von Object Pascal, unterstützt anonyme Funktionen (formal, anonyme Methoden) nativ seit Delphi 2009. Der Oxygene Object Pascal-Dialekt unterstützt sie ebenfalls.
Objective-C (Mac OS X 10.6+) Y. Genannte Blöcke; Neben Objective-C können Blöcke auch für C und C ++ verwendet werden, wenn auf der Apple-Plattform programmiert wird.
Pascal N.
Perl Y. [26]
PHP Y. Ab PHP 5.3.0 werden echte anonyme Funktionen unterstützt.[27] Früher wurden nur teilweise anonyme Funktionen unterstützt, die ähnlich wie die Implementierung von C # funktionierten.
PL / I. N.
Python Y. Python unterstützt anonyme Funktionen über die Lambda-Syntax.[28] Dies unterstützt nur Ausdrücke, keine Anweisungen.
R. Y.
Schläger Y. [29]
Raku Y.
Rexx N.
Rollenspiel N.
Rubin Y. Rubys anonyme Funktionen, die von Smalltalk geerbt wurden, werden als Blöcke bezeichnet.
Rost Y.
Scala Y.
Planen Y.
Smalltalk Y. Die anonymen Funktionen von Smalltalk werden als Blöcke bezeichnet.
Standard ML Y.
Schnell Y. Die anonymen Funktionen von Swift werden als Closures bezeichnet.
Typoskript Y.
Tcl Y. [30]
Vala Y. [30]
Visual Basic .NET v9 Y.
Visual Prolog v 7.2 Y.
WLanguage v25 Y. Die von der WinDev / WebDev / WinDev Mobile-Suite verwendete W-Sprache von PCSoft unterstützt ab Version 25 (2019) anonyme Funktionen.
Wolfram Sprache Y.

Beispiele[edit]

Zahlreiche Sprachen unterstützen anonyme Funktionen oder ähnliches.

APL[edit]

Nur einige Dialekte unterstützen anonyme Funktionen, entweder als dfns, im stillschweigenden Stil oder als Kombination aus beiden.

      f{×} ⍝ As a dfn
      f 1 2 3
1 4 9     
      g⊢×⊢   ⍝ As a tacit 3-train (fork)
      g 1 2 3
1 4 9
      h×    ⍝ As a derived tacit function
      h 1 2 3
1 4 9

C (nicht standardmäßige Erweiterung)[edit]

Die anonyme Funktion wird nicht von der Standard-Programmiersprache C unterstützt, sondern von einigen C-Dialekten, wie z GCC und Clang.

GCC[edit]

Die GNU Compiler Collection (GCC) unterstützt anonyme Funktionen, die durch verschachtelte Funktionen und Anweisungsausdrücke gemischt werden. Es hat die Form:

( { return_type anonymous_functions_name (parameters) { function_body } anonymous_functions_name; } )

Das folgende Beispiel funktioniert nur mit GCC. Aufgrund der Art und Weise, wie Makros erweitert werden, wird die l_body darf keine Kommas außerhalb von Klammern enthalten; GCC behandelt das Komma als Trennzeichen zwischen Makroargumenten. Das Argument l_ret_type kann entfernt werden, wenn __typeof__ ist verfügbar; im folgenden Beispiel mit __typeof__ on array würde testtype * zurückgeben, der bei Bedarf für den tatsächlichen Wert dereferenziert werden kann.

#include 

//* this is the definition of the anonymous function */
#define lambda(l_ret_type, l_arguments, l_body)        
  ({                                                   
   l_ret_type l_anonymous_functions_name l_arguments   
   l_body                                              
   &l_anonymous_functions_name;                        
   })

#define forEachInArray(fe_arrType, fe_arr, fe_fn_body)                                    
{                                                                                         
  int i=0;                                                                                
  for(;i
}

typedef struct __test
{
  int a;
  int b;
} testtype;

void printout(const testtype * array)
{
  int i;
  for ( i = 0; i < 3; ++ i )
    printf("%d %dn", array[i].a, array[i].b);
  printf("n");
}

int main(void)
{
  testtype array[] = { {0,1}, {2,3}, {4,5} };

  printout(array);
  /* the anonymous function is given as function for the foreach */
  forEachInArray(testtype, array,
    lambda (testtype, (void *item),
    {
      int temp = (*( testtype *) item).a;
      (*( testtype *) item).a = (*( testtype *) item).b;
      (*( testtype *) item).b = temp;
      return (*( testtype *) item);
    }));
  printout(array);
  return 0;
}

Clang (C, C ++, Ziel-C, Ziel-C ++)[edit]

Clang unterstützt anonyme Funktionen, sogenannte Blöcke, die die Form haben:

^return_type ( parameters ) { function_body }

Der Typ der obigen Blöcke ist return_type (^)(parameters).

Verwendung der oben genannten Blöcke Erweiterung und Grand Central Dispatch (libdispatch) könnte der Code einfacher aussehen:

#include 
#include 

int main(void) {
  void (^count_loop)() = ^{
    for (int i = 0; i < 100; i++)
      printf("%dn", i);
    printf("ah ah ahn");
  };

/* Pass as a parameter to another function */
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), count_loop);

/* Invoke directly */
  count_loop();

  return 0;
}

Der Code mit Blöcken sollte mit kompiliert werden -fblocks und verknüpft mit -lBlocksRuntime

C ++ (seit C ++ 11)[edit]

C ++ 11 unterstützt anonyme Funktionen, die aufgerufen werden Lambda-Ausdrücke, die die Form haben:

[capture](parameters) -> return_type { function_body }

Dies ist ein Beispiel für einen Lambda-Ausdruck:

[](int x, int y) -> int { return x + y; }

C ++ 11 unterstützt auch Schließungen. Verschlüsse werden in eckigen Klammern definiert [and ] in der Erklärung des Lambda-Ausdrucks. Der Mechanismus ermöglicht die Erfassung dieser Variablen nach Wert oder Referenz. Die folgende Tabelle zeigt dies:

[]        //no variables defined. Attempting to use any external variables in the lambda is an error.
[x, &y]   //x is captured by value, y is captured by reference
[&]       //any external variable is implicitly captured by reference if used
[=]       //any external variable is implicitly captured by value if used
[&, x]    //x is explicitly captured by value. Other variables will be captured by reference
[=, &z]   //z is explicitly captured by reference. Other variables will be captured by value

Vom Wert erfasste Variablen sind standardmäßig konstant. Hinzufügen mutable Nach der Parameterliste sind sie nicht konstant.

Die folgenden zwei Beispiele zeigen die Verwendung eines Lambda-Ausdrucks:

std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
std::for_each(begin(some_list), end(some_list), 
              [&total](int x) {	total += x; });

Dies berechnet die Summe aller Elemente in der Liste. Die Variable total wird als Teil des Abschlusses der Lambda-Funktion gespeichert. Da es sich um eine Referenz auf die Stapelvariable handelt totalkann es seinen Wert ändern.

std::vector<int> some_list{ 1, 2, 3, 4, 5 };
int total = 0;
int value = 5;
std::for_each(begin(some_list), end(some_list), 
             [&total, value, this](int x) { total += x * value * this->some_func(); });

Dies wird verursachen total als Referenz gespeichert werden, aber value wird als Kopie gespeichert.

Die Erfassung von this ist besonders. Es kann nur nach Wert erfasst werden, nicht nach Referenz. this kann nur erfasst werden, wenn die nächstgelegene umschließende Funktion eine nicht statische Elementfunktion ist. Das Lambda hat in Bezug auf geschützte / private Mitglieder den gleichen Zugriff wie das Mitglied, das es erstellt hat.

Wenn this Wird entweder explizit oder implizit erfasst, wird auch der Umfang der eingeschlossenen Klassenmitglieder getestet. Zugriff auf Mitglieder von this benötigt keine explizite Verwendung von this-> Syntax.

Die spezifische interne Implementierung kann variieren, es wird jedoch erwartet, dass eine Lambda-Funktion, die alles als Referenz erfasst, den tatsächlichen Stapelzeiger der Funktion speichert, in der sie erstellt wurde, und nicht einzelne Verweise auf Stapelvariablen. Da die meisten Lambda-Funktionen jedoch klein und lokal sind, sind sie wahrscheinlich Kandidaten für Inlining und benötigen daher keinen zusätzlichen Speicher für Referenzen.

Wenn ein Abschlussobjekt, das Verweise auf lokale Variablen enthält, nach dem innersten Blockbereich seiner Erstellung aufgerufen wird, ist das Verhalten undefiniert.

Lambda-Funktionen sind Funktionsobjekte eines implementierungsabhängigen Typs. Der Name dieses Typs steht nur dem Compiler zur Verfügung. Wenn der Benutzer eine Lambda-Funktion als Parameter verwenden möchte, muss der Parametertyp ein Vorlagentyp sein oder er muss einen erstellen std::function oder ein ähnliches Objekt, um den Lambda-Wert zu erfassen. Die Verwendung der auto Schlüsselwort kann helfen, die Lambda-Funktion zu speichern,

auto my_lambda_func = [&](int x) { /*...*/ };
auto my_onheap_lambda_func = new auto([=](int x) { /*...*/ });

Hier ist ein Beispiel für das Speichern anonymer Funktionen in Variablen, Vektoren und Arrays. und Übergabe als benannte Parameter:

#include 
#include 
#include 

double eval(std::function<double(double)> f, double x = 2.0) {
  return f(x);
}

int main() {
  std::function<double(double)> f0 = [](double x) { return 1; };
  auto f1 = [](double x) { return x; };
  decltype(f0) fa[3] = {f0, f1, [](double x) { return x * x; }};
  std::vector<decltype(f0)> fv = {f0, f1};
  fv.push_back([](double x) { return x * x; });
  for (size_t i = 0; i < fv.size(); i++) {
    std::cout << fv[i](2.0) << std::endl;
  }
  for (size_t i = 0; i < 3; i++) {
    std::cout << fa[i](2.0) << std::endl;
  }
  for (auto& f : fv) {
    std::cout << f(2.0) << std::endl;
  }
  for (auto& f : fa) {
    std::cout << f(2.0) << std::endl;
  }
  std::cout << eval(f0) << std::endl;
  std::cout << eval(f1) << std::endl;
  std::cout << eval([](double x) { return x * x; }) << std::endl;
}

Ein Lambda-Ausdruck mit einer leeren Erfassungsspezifikation ([]) kann implizit in einen Funktionszeiger mit demselben Typ konvertiert werden, mit dem das Lambda deklariert wurde. Das ist also legal:

auto a_lambda_func = [](int x) { /*...*/ };
void (* func_ptr)(int) = a_lambda_func;
func_ptr(4); //calls the lambda.

Die Boost-Bibliothek bietet auch eine eigene Syntax für Lambda-Funktionen mit der folgenden Syntax:[31]

for_each(a.begin(), a.end(), std::cout << _1 << ' ');

C #[edit]

In C # wurde die Unterstützung für anonyme Funktionen durch die verschiedenen Versionen des Sprachcompilers vertieft. Die im November 2007 mit .NET Framework v3.5 veröffentlichte Sprache v3.0 unterstützt alle anonymen Funktionen vollständig. C # nennt sie Lambda-Ausdrückefolgt der Originalversion anonymer Funktionen, dem Lambda-Kalkül.[32]

// the first int is the x' type
// the second int is the return type
// http://msdn.microsoft.com/en-us/library/bb549151.aspx" />
Func<int,int> foo = x => x * x;
Console.WriteLine(foo(7));

Während die Funktion anonym ist, kann sie keiner implizit typisierten Variablen zugewiesen werden, da die Lambda-Syntax zum Bezeichnen einer anonymen Funktion oder eines Ausdrucksbaums verwendet werden kann und die Auswahl vom Compiler nicht automatisch entschieden werden kann. ZB funktioniert das nicht:

// will NOT compile!
var foo = (int x) => x * x;

Ein Lambda-Ausdruck kann jedoch an der Typinferenz teilnehmen und als Methodenargument verwendet werden, z. B. um anonyme Funktionen mit der verfügbaren Map-Funktion zu verwenden System.Collections.Generic.List (in dem ConvertAll() Methode):

// Initialize the list:
var values = new List<int>() { 7, 13, 4, 9, 3 };
// Map the anonymous function over all elements in the list, return the new list
var foo = values.ConvertAll(d => d * d) ; 
// the result of the foo variable is of type System.Collections.Generic.List

Frühere Versionen von C # hatten eine eingeschränktere Unterstützung für anonyme Funktionen. C # v1.0, das im Februar 2002 mit .NET Framework v1.0 eingeführt wurde, bot teilweise anonyme Funktionsunterstützung durch die Verwendung von Delegaten. Dieses Konstrukt ähnelt etwas PHP-Delegaten. In C # 1.0 sind Delegaten wie Funktionszeiger, die auf eine explizit benannte Methode innerhalb einer Klasse verweisen. (Im Gegensatz zu PHP wird der Name zum Zeitpunkt der Verwendung des Delegaten nicht benötigt.) C # v2.0, das im November 2005 mit .NET Framework v2.0 veröffentlicht wurde, führte das Konzept anonymer Methoden ein, um unbenannte Inline-Anweisungen zu schreiben Blöcke, die in einem Delegatenaufruf ausgeführt werden können. C # 3.0 unterstützt diese Konstrukte weiterhin, unterstützt jedoch auch das Lambda-Expressionskonstrukt.

Dieses Beispiel wird in C # 3.0 kompiliert und weist die drei Formen auf:

    public class TestDriver
    {
        delegate int SquareDelegate(int d);
        static int Square(int d)
        {
            return d * d;
        }
 
        static void Main(string[] args)
        {
            // C# 1.0: Original delegate syntax needed 
            // initializing with a named method.
            SquareDelegate A = new SquareDelegate(Square);
            System.Console.WriteLine(A(3));
 
            // C# 2.0: A delegate can be initialized with
            // inline code, called an "anonymous method". This
            // method takes an int as an input parameter.
            SquareDelegate B = delegate(int d) { return d * d; };
            System.Console.WriteLine(B(5));
 
            // C# 3.0. A delegate can be initialized with
            // a lambda expression. The lambda takes an int, and returns an int. 
            // The type of x is inferred by the compiler.
            SquareDelegate C = x => x * x;
            System.Console.WriteLine(C(7));
 
            // C# 3.0. A delegate that accepts one input and
            // returns one output can also be implicitly declared with the Func<> type.
            System.Func<int,int> D = x => x * x;
            System.Console.WriteLine(D(9));
        } 
    }

Bei der C # 2.0-Version übernimmt der C # -Compiler den Codeblock der anonymen Funktion und erstellt eine statische private Funktion. Intern erhält die Funktion natürlich einen generierten Namen. Dieser generierte Name basiert auf dem Namen der Methode, in der der Delegat deklariert ist. Der Name wird jedoch nur durch Verwendung von Reflection dem Anwendungscode ausgesetzt.

Bei der C # 3.0-Version gilt der gleiche Mechanismus.

ColdFusion Markup Language (CFML)[edit]

fn = function(){
  // statements
};

CFML unterstützt alle Anweisungen innerhalb der Funktionsdefinition, nicht nur Ausdrücke.

CFML unterstützt rekursive anonyme Funktionen:

factorial = function(n){
    return n > 1 ? n * factorial(n-1) : 1;
};

Anonyme CFML-Funktionen implementieren das Schließen.

D.[edit]

D verwendet Inline-Delegaten, um anonyme Funktionen zu implementieren. Die vollständige Syntax für einen Inline-Delegaten lautet

return_type delegate(arguments){/*body*/}

Wenn eindeutig, der Rückgabetyp und das Schlüsselwort delegieren kann ausgelassen werden.

(x){return x*x;}
delegate (x){return x*x;} // if more verbosity is needed
(int x){return x*x;} // if parameter type cannot be inferred
delegate (int x){return x*x;} // ditto
delegate double(int x){return x*x;} // if return type must be forced manually

Seit Version 2.0 weist D dem Heap Schließungen zu, es sei denn, der Compiler kann nachweisen, dass dies nicht erforderlich ist. das scope Das Schlüsselwort kann zum Erzwingen der Stapelzuweisung verwendet werden. Seit Version 2.058 kann die Kurzschreibweise verwendet werden:

x => x*x;
(int x) => x*x;
(x,y) => x*y;
(int x, int y) => x*y;

Eine anonyme Funktion kann einer Variablen zugewiesen und wie folgt verwendet werden:

auto sqr = (double x){return x*x;};
double y = sqr(4);

Pfeil[edit]

Dart unterstützt anonyme Funktionen.[8]

var sqr = (x) => x * x;
print(sqr(5));

oder

print(((x) => x * x)(5));

Delphi[edit]

Delphi hat in Version 2009 anonyme Funktionen eingeführt.

program demo;

type
  TSimpleProcedure = reference to procedure;
  TSimpleFunction = reference to function(const x: string): Integer;

var
  x1: TSimpleProcedure;
  y1: TSimpleFunction;

begin
  x1 := procedure
    begin
      Writeln('Hello World');
    end;
  x1;   //invoke anonymous method just defined

  y1 := function(const x: string): Integer
    begin
      Result := Length(x);
    end;
  Writeln(y1('bar')); 
end.

PascalABC.NET[edit]

PascalABC.NET unterstützt anonyme Funktionen mit Lambda-Syntax

begin
  var n := 10000000;
  var pp := Range(1,n)
    .Select(x->Rec(Random(),Random()))
    .Where(p->sqr(p.Item1)+sqr(p.Item2)<1)
    .Count/n*4;
  Print(pp);
end.

Elixier[edit]

Elixier benutzt den Verschluss fn für anonyme Funktionen.[10]

sum = fn(a, b) -> a + b end
sum.(4, 3)
#=> 7

square = fn(x) -> x * x end
Enum.map [1, 2, 3, 4], square
#=> [1, 4, 9, 16]

Erlang[edit]

Erlang verwendet eine Syntax für anonyme Funktionen, die der von benannten Funktionen ähnelt.[11]

% Anonymous function bound to the Square variable
Square = fun(X) -> X * X end.

% Named function with the same functionality
square(X) -> X * X.

Gehen[edit]

Go unterstützt anonyme Funktionen.[15]

foo := func(x int) int {
	return x * x
}
fmt.Println(foo(10))

Haskell[edit]

Haskell verwendet eine präzise Syntax für anonyme Funktionen (Lambda-Ausdrücke).

Lambda-Ausdrücke sind vollständig in die Typinferenz-Engine integriert und unterstützen alle Syntaxen und Merkmale “gewöhnlicher” Funktionen (mit Ausnahme der Verwendung mehrerer Definitionen für den Mustervergleich, da die Argumentliste nur einmal angegeben wird).

 map (x -> x * x) [1..5] -- returns [1, 4, 9, 16, 25]

Die folgenden sind alle gleichwertig:

 f x y = x + y
 f x = y -> x + y
 f = x y -> x + y

Haxe[edit]

In Haxe heißen anonyme Funktionen Lambda und verwenden die Syntax function(argument-list) expression; .

var f = function(x) return x*x;
f(8); // 64

(function(x,y) return x+y)(5,6); // 11

Java[edit]

Java unterstützt anonyme Funktionen mit dem Namen Lambda-Ausdrückebeginnend mit JDK 8.[33]

Ein Lambda-Ausdruck besteht aus einer durch Kommas getrennten Liste der in Klammern eingeschlossenen formalen Parameter, einem Pfeiltoken (->) und einem Textkörper. Datentypen der Parameter können immer weggelassen werden, ebenso wie die Klammern, wenn nur ein Parameter vorhanden ist. Der Body kann aus einer Anweisung oder einem Anweisungsblock bestehen.[34]

// with no parameter
() -> System.out.println("Hello, world.")

// with one parameter (this example is an identity function).
a -> a

// with one expression
(a, b) -> a + b

// with explicit type information
(long id, String name) -> "id: " + id + ", name:" + name

// with a code block
(a, b) -> { return a + b; }

// with multiple statements in the lambda body. It needs a code block.
// This example also includes two nested lambda expressions (the first one is also a closure).
(id, defaultPrice) -> {
    Optional<Product> product = productList.stream().filter(p -> p.getId() == id).findFirst();
    return product.map(p -> p.getPrice()).orElse(defaultPrice);
}

Lambda-Ausdrücke werden in “funktionale Schnittstellen” konvertiert (definiert als Schnittstellen, die neben einer oder mehreren Standard- oder statischen Methoden nur eine abstrakte Methode enthalten).[34] wie im folgenden Beispiel:

public class Calculator {
    interface IntegerMath {
        int operation(int a, int b);

        default IntegerMath swap() {
            return (a, b) -> operation(b, a);
        }
    }

    private static int apply(int a, int b, IntegerMath op) {
        return op.operation(a, b);
    }

    public static void main(String... args) {
        IntegerMath addition = (a, b) -> a + b;
        IntegerMath subtraction = (a, b) -> a - b;
        System.out.println("40 + 2 = " + apply(40, 2, addition));
        System.out.println("20 - 10 = " + apply(20, 10, subtraction));
        System.out.println("10 - 20 = " + apply(20, 10, subtraction.swap()));    
    }
}

In diesem Beispiel wird eine Funktionsschnittstelle aufgerufen IntegerMath wird deklariert. Lambda-Ausdrücke, die implementieren IntegerMath werden an die übergeben apply() auszuführende Methode. Standardmethoden wie swap Definieren Sie Methoden für Funktionen.

In Java 8 wurde ein weiterer Mechanismus namens Methodenreferenz (der Operator ::) eingeführt, um ein Lambda für eine vorhandene Methode zu erstellen. Eine Methodenreferenz gibt nicht die Anzahl oder Art der Argumente an, da diese aus der abstrakten Methode der Funktionsschnittstelle extrahiert werden.

IntBinaryOperator sum = Integer::sum;

Im obigen Beispiel die Funktionsschnittstelle IntBinaryOperator deklariert eine abstrakte Methode int applyAsInt(int, int)Der Compiler sucht also nach einer Methode int sum(int, int) in der Klasse java.lang.Integer.

Java-Einschränkungen[edit]

Java 8 Lambdas haben die folgenden Einschränkungen:

  • Lambdas können aktivierte Ausnahmen auslösen, aber solche Lambdas funktionieren nicht mit den von der Collection-API verwendeten Schnittstellen.
  • Auf Variablen im Gültigkeitsbereich, in denen das Lambda deklariert ist, kann nur innerhalb des Lambdas zugegriffen werden, wenn sie tatsächlich endgültig sind, dh wenn die Variable nicht innerhalb oder außerhalb des Lambda-Gültigkeitsbereichs mutiert ist.

JavaScript[edit]

JavaScript / ECMAScript unterstützt anonyme Funktionen.

alert((function(x){
  return x * x;
})(10));

ES6 unterstützt die Syntax “Pfeilfunktion”, wobei a => Das Symbol trennt die Parameterliste der anonymen Funktion vom Textkörper:

Dieses Konstrukt wird häufig in Lesezeichen verwendet. Um beispielsweise den Titel des aktuellen Dokuments (in der Titelleiste des Fensters sichtbar) in seine URL zu ändern, scheint das folgende Lesezeichen zu funktionieren.

javascript:document.title=location.href;

Da die Zuweisungsanweisung jedoch einen Wert (die URL selbst) zurückgibt, erstellen viele Browser tatsächlich eine neue Seite, um diesen Wert anzuzeigen.

Stattdessen kann eine anonyme Funktion verwendet werden, die keinen Wert zurückgibt:

javascript:(function(){document.title=location.href;})();

Die Funktionsanweisung im ersten (äußeren) Klammerpaar deklariert eine anonyme Funktion, die dann ausgeführt wird, wenn sie mit dem letzten Klammerpaar verwendet wird. Dies entspricht fast dem Folgenden, mit dem die Umgebung gefüllt wird f im Gegensatz zu einer anonymen Funktion.

javascript:var f = function(){document.title=location.href;}; f();

Verwenden Sie void (), um neue Seiten für beliebige anonyme Funktionen zu vermeiden:

javascript:void(function(){return document.title=location.href;}());

oder nur:

javascript:void(document.title=location.href);

JavaScript verfügt über syntaktische Feinheiten für die Semantik des Definierens, Aufrufens und Auswertens anonymer Funktionen. Diese unterschwelligen Nuancen sind eine direkte Folge der Bewertung von Klammerausdrücken. Die folgenden Konstrukte, die als sofort aufgerufener Funktionsausdruck bezeichnet werden, veranschaulichen dies:

und

Darstellen “function(){ ... }” durch fist die Form der Konstrukte eine Klammer innerhalb einer Klammer (f()) und eine Klammer, die auf eine Klammer angewendet wird (f)().

Beachten Sie die allgemeine syntaktische Mehrdeutigkeit eines Ausdrucks in Klammern, die Argumente in Klammern für eine Funktion und die Klammern um die formalen Parameter in einer Funktionsdefinition. Insbesondere definiert JavaScript a , (Komma-) Operator im Kontext eines Klammerausdrucks. Es ist kein Zufall, dass die syntaktischen Formen für einen Ausdruck und die Argumente einer Funktion übereinstimmen (wobei die Syntax der formalen Funktionsparameter ignoriert wird)! Wenn f wird in den obigen Konstrukten nicht identifiziert, werden sie (()) und ()(). Die erste liefert keinen syntaktischen Hinweis auf eine residente Funktion, aber die zweite MUSS die erste Klammer als eine Funktion bewerten, um legales JavaScript zu sein. (Nebenbei: zum Beispiel die ()könnte sein ([], {}, 42, “abc”, function () {}), solange der Ausdruck eine Funktion ergibt.)

Eine Funktion ist auch eine Objektinstanz (ebenfalls sind Objekte Funktionsinstanzen) und die Objektliteral-Notationsklammern. {} werden bei der Definition einer Funktion auf diese Weise verwendet (im Gegensatz zur Verwendung) new Function(...)). In einem sehr weiten, nicht strengen Sinne (insbesondere da globale Bindungen kompromittiert sind), einer willkürlichen Folge von geschweiften JavaScript-Anweisungen {stuff}kann als fester Punkt von angesehen werden

(function(){( function(){( ... {( function(){stuff}() )} ... )}() )}() )

Richtiger, aber mit Einschränkungen,

( function(){stuff}() ) ~=
   A_Fixed_Point_of(
      function(){ return function(){ return ... { return function(){stuff}() } ... }() }()
   )

Beachten Sie die Auswirkungen der anonymen Funktion in den folgenden JavaScript-Fragmenten:

  • function(){ ... }() ohne Umgebung ()ist im Allgemeinen nicht legal
  • (f=function(){ ... }) vergisst nicht f global anders als (function f(){ ... })
Leistungsmetriken zur Analyse der räumlichen und zeitlichen Komplexität von Funktionsaufrufen, Aufrufstapeln usw. in einer JavaScript-Interpreter-Engine lassen sich mit diesen letzten anonymen Funktionskonstrukten problemlos implementieren. Aus den Auswirkungen der Ergebnisse können einige rekursive und iterative Implementierungsdetails einer Engine abgeleitet werden, insbesondere die Schwanzrekursion.

Julia[edit]

In Julia werden anonyme Funktionen mit der Syntax definiert (arguments)->(expression),

julia> f = x -> x*x; f(8)
64
julia> ((x,y)->x+y)(5,6)
11

Lispeln[edit]

Lisp und Scheme unterstützen anonyme Funktionen mit dem Konstrukt “Lambda”, das auf die Lambda-Rechnung verweist. Clojure unterstützt anonyme Funktionen mit der Sonderform “fn” und der Lesersyntax # ().

(lambda (arg) (* arg arg))

Common Lisp[edit]

Common Lisp hat das Konzept von Lambda-Ausdrücken. Ein Lambda-Ausdruck wird als Liste mit dem Symbol “Lambda” als erstem Element geschrieben. Die Liste enthält dann die Argumentliste, Dokumentation oder Deklarationen sowie einen Funktionskörper. Lambda-Ausdrücke können in Lambda-Formularen und mit dem speziellen Operator “Funktion” verwendet werden.

(function (lambda (arg) (do-something arg)))

“Funktion” kann als # ‘abgekürzt werden. Auch Makro Lambda existiert, die sich zu einer Funktionsform erweitert:

; using sharp quote
#'(lambda (arg) (do-something arg))
; using the lambda macro:
(lambda (arg) (do-something arg))

Eine typische Verwendung anonymer Funktionen in Common Lisp besteht darin, sie an Funktionen höherer Ordnung wie zu übergeben mapcar, wendet eine Funktion auf jedes Element einer Liste an und gibt eine Liste der Ergebnisse zurück.

(mapcar #'(lambda (x) (* x x))
        '(1 2 3 4))
; -> (1 4 9 16)

Das Lambda-Form in Common Lisp erlaubt a Lambda-Ausdruck in einem Funktionsaufruf geschrieben werden:

((lambda (x y)
   (+ (sqrt x) (sqrt y)))
 10.0
 12.0)

Anonyme Funktionen in Common Lisp können später auch globale Namen erhalten:

(setf (symbol-function 'sqr)
      (lambda (x) (* x x)))
; which allows us to call it using the name SQR:
(sqr 10.0)

Planen[edit]

Schema benannte Funktionen ist einfach syntaktischer Zucker für anonyme Funktionen, die an Namen gebunden sind:

(define (somename arg)
  (do-something arg))

erweitert (und ist äquivalent) zu

(define somename
  (lambda (arg)
    (do-something arg)))

Clojure[edit]

Clojure unterstützt anonyme Funktionen über das Sonderformular “fn”:

Es gibt auch eine Lesersyntax zum Definieren eines Lambda:

# (+ % %2%3) ; Defines an anonymous function that takes three arguments and sums them.

Wie Scheme sind Clojures “benannte Funktionen” einfach syntaktischer Zucker für Lambdas, die an Namen gebunden sind:

(defn func [arg] (+ 3 arg))

erweitert sich zu:

(def func (fn [arg] (+ 3 arg)))

Lua[edit]

In Lua (ähnlich wie in Schema) sind alle Funktionen anonym. EIN benannte Funktion in Lua ist einfach eine Variable, die einen Verweis auf ein Funktionsobjekt enthält.[35]

So in Lua

function foo(x) return 2*x end

ist nur syntaktischer Zucker für

foo = function(x) return 2*x end

Ein Beispiel für die Verwendung anonymer Funktionen für die Sortierung in umgekehrter Reihenfolge:

table.sort(network, function(a,b)
  return a.name > b.name
end)

Wolfram Language, Mathematica[edit]

Die Wolfram-Sprache ist die Programmiersprache von Mathematica. Anonyme Funktionen sind wichtig für die Programmierung der letzteren. Es gibt verschiedene Möglichkeiten, sie zu erstellen. Im Folgenden finden Sie einige anonyme Funktionen, die eine Zahl erhöhen. Der erste ist der häufigste. #1 bezieht sich auf das erste Argument und & markiert das Ende der anonymen Funktion.

     #1+1&
     Function[x,x+1]
     x [Function] x+1

Also zum Beispiel:

    f:= #1^2&;f[8]
     64
    #1+#2&[5,6]
     11

Außerdem verfügt Mathematica über ein zusätzliches Konstrukt, um rekursive anonyme Funktionen zu erstellen. Das Symbol ‘# 0’ bezieht sich auf die gesamte Funktion. Die folgende Funktion berechnet die Fakultät ihrer Eingabe:

     If[#1 == 1, 1, #1 * #0[#1-1]]&

Zum Beispiel wären 6 Fakultäten:

     If[#1 == 1, 1, #1 * #0[#1-1]]&[6]
720

MATLAB, Oktave[edit]

Anonyme Funktionen in MATLAB oder Octave werden mithilfe der Syntax definiert @(argument-list)expression. Alle Variablen, die nicht in der Argumentliste enthalten sind, werden vom umschließenden Bereich geerbt.

 > f = @(x)x*x; f(8)
 ans =  64
 > (@(x,y)x+y)(5,6) % Only works in Octave
 ans =  11

Maxima[edit]

In Maxima werden anonyme Funktionen mithilfe der Syntax definiert lambda(argument-list,expression),

 f: lambda([x],x*x); f(8);
 64

 lambda([x,y],x+y)(5,6);
 11

ML[edit]

Die verschiedenen Dialekte von ML unterstützen anonyme Funktionen.

OCaml[edit]

OCaml-Funktionen müssen keine Namen haben. Sie können anonym sein. Hier ist zum Beispiel eine anonyme Funktion, die ihre Eingabe erhöht: fun x -> x + 1. Hier ist fun ein Schlüsselwort, das eine anonyme Funktion angibt, x ist das Argument und -> trennt das Argument vom Textkörper.

Wir haben jetzt zwei Möglichkeiten, eine Inkrementfunktion zu schreiben:

let inc x = x + 1
let inc = fun x -> x+1

Sie sind syntaktisch unterschiedlich, aber semantisch äquivalent. Das heißt, obwohl sie unterschiedliche Schlüsselwörter enthalten und einige Bezeichner an verschiedenen Stellen platzieren, bedeuten sie dasselbe.

Anonyme Funktionen werden auch Lambda-Ausdrücke genannt, ein Begriff, der aus dem Lambda-Kalkül stammt, einem mathematischen Berechnungsmodell in demselben Sinne wie Turing-Maschinen ein Berechnungsmodell. In der Lambda-Rechnung würde Spaß x -> e λx.e geschrieben. Das λ bezeichnet eine anonyme Funktion.

Syntax.

Statische Semantik.

Wenn wir annehmen, dass x1: t1 und x2: t2 und … und xn: tn, können wir daraus schließen, dass e: u, dann Spaß x1 … xn -> e: t1 -> t2 -> … -> tn -> u. Dynamische Semantik.

Eine anonyme Funktion ist bereits ein Wert. Es ist keine Berechnung durchzuführen.

Ausschnitt aus CS3110, Cornell, unterrichtet von Michael R. Clarkson, Robert L. Constable, Nate Foster, Michael D. George, Dan Grossman, Daniel P. Huttenlocher, Dexter Kozen, Greg Morrisett, Andrew C. Myers, Radu Rugina und Ramin Zabih. [36]

F #[edit]

F # unterstützt anonyme Funktionen,[12] wie folgt:

(fun x -> x * x) 20 // 400

Standard ML[edit]

Standard ML unterstützt anonyme Funktionen wie folgt:

fn  arg => arg * arg

Shell der nächsten Generation[edit]

Die Shell der nächsten Generation verfügt aufgrund ihrer Verbreitung in der Sprache und unterschiedlicher Anwendungsfälle über mehrere Syntaxen für anonyme Funktionen.

Syntax:

f = X*X; f(8)                       # Result: 64
f = { A*B+C }; f(2,3,4)             # Result: 10
f = F(x:Int, y:Int) x*y+2; f(3, 4)  # Result: 14

f = "${X} is all about ${Y}"
f("programming", "semantics")       # Result: "programming is all about semantics"

Anwendungsbeispiele für anonyme Funktionen:

[0,1,2].map(X*2)                    # Result: [0,2,4]

data = {"a": "xxx", "b": "yyy"}
data.map("${X} is ${Y}")            # Result: ["a is xxx", "b is yyy"]

Nim[edit]

Nim unterstützt anonyme Funktionen mit mehreren Zeilen und mehreren Ausdrücken. [37]

var anon = proc (var1, var2: int): int = var1 + var2
assert anon(1, 2) == 3

Mehrzeiliges Beispiel:

var anon = func (x: int): bool =
             if x > 0:
               result = true
             else: 
               result = false

assert anon(9)

Anonyme Funktionen können als Eingabeparameter anderer Funktionen übergeben werden:

var cities = @["Frankfurt", "Tokyo", "New York"]

cities.sort(
  proc (x, y: string): int = cmp(x.len, y.len)
)

Eine anonyme Funktion ist im Grunde eine Funktion ohne Namen.

Perl[edit]

Perl 5[edit]

Perl 5 unterstützt anonyme Funktionen,[26] wie folgt:

(sub { print "I got calledn" })->();         # 1. fully anonymous, called as created

my $squarer = sub { my $x = shift; $x * $x }; # 2. assigned to a variable

sub curry {
    my ($sub, @args) = @_;
    return sub { $sub->(@args, @_) };         # 3. as a return value of another function
}

# example of currying in Perl programming
sub sum { my $tot = 0; $tot += $_ for @_; $tot } # returns the sum of its arguments
my $curried = curry &sum, 5, 7, 9;
print $curried->(1,2,3), "n";    # prints 27 ( = 5 + 7 + 9 + 1 + 2 + 3 )

Andere Konstrukte nehmen nackte Blöcke als Argumente, die eine Funktion erfüllen, die den Lambda-Funktionen eines Parameters ähnelt, jedoch nicht die gleiche Parameterübergabekonvention wie Funktionen haben – @_ ist nicht festgelegt.

my @squares = map { $_ * $_ } 1..10;   # map and grep don't use the 'sub' keyword
my @square2 = map $_ * $_, 1..10;      # braces unneeded for one expression

my @bad_example = map { print for @_ } 1..10; # values not passed like normal Perl function

PHP[edit]

Vor 4.0.1 hatte PHP keine anonyme Funktionsunterstützung.[38]

PHP 4.0.1 bis 5.3[edit]

PHP 4.0.1 führte die create_function Das war die anfängliche anonyme Funktionsunterstützung. Dieser Funktionsaufruf erstellt eine neue zufällig benannte Funktion und gibt ihren Namen zurück (als Zeichenfolge).

$foo = create_function('$x', 'return $x*$x;');
$bar = create_function("$x", "return $x*$x;");
echo $foo(10);

Die Argumentliste und der Funktionskörper müssen in einfachen Anführungszeichen stehen, oder die Dollarzeichen müssen maskiert werden. Ansonsten geht PHP von “$x“bedeutet die Variable $x und wird es in den String einfügen (obwohl möglicherweise nicht vorhanden), anstatt zu verlassen “$x“in der Zeichenfolge. Bei Funktionen mit Anführungszeichen oder Funktionen mit vielen Variablen kann es ziemlich mühsam werden, sicherzustellen, dass der beabsichtigte Funktionskörper das ist, was PHP interpretiert.

Jeder Aufruf von create_function macht eine neue Funktion, die für den Rest des Programms existiert und nicht sein kann Müll gesammelt, Speicher im Programm irreversibel verwenden. Wenn dies verwendet wird, um anonyme Funktionen mehrmals zu erstellen, z. B. in einer Schleife, kann dies zu Problemen wie Speicheraufblähen führen.

PHP 5.3[edit]

PHP 5.3 hat eine neue Klasse namens hinzugefügt Closure und magische Methode __invoke() das macht eine Klasseninstanz aufrufbar.[39]

$x = 3;
$func = function($z) { return $z *= 2; };
echo $func($x); // prints 6

In diesem Beispiel $func ist eine Instanz von Closure und echo $func($x) ist äquivalent zu echo $func->__invoke($x). PHP 5.3 ahmt anonyme Funktionen nach, unterstützt jedoch keine echten anonymen Funktionen, da PHP-Funktionen immer noch keine erstklassigen Objekte sind.

PHP 5.3 unterstützt Schließungen, aber die Variablen müssen explizit als solche angegeben werden:

$x = 3;
$func = function() use(&$x) { $x *= 2; };
$func();
echo $x; // prints 6

Die Variable $x ist durch Bezugnahme gebunden, so dass der Aufruf von $func ändert es und die Änderungen sind außerhalb der Funktion sichtbar.

Prologs Dialekte[edit]

Logtalk[edit]

Logtalk verwendet die folgende Syntax für anonyme Prädikate (Lambda-Ausdrücke):

{FreeVar1, FreeVar2, ...}/[LambdaParameter1, LambdaParameter2, ...]>>Goal

Ein einfaches Beispiel ohne freie Variablen und mit einem Listenzuordnungsprädikat ist:

| ?- meta::map([X,Y]>>(Y is 2*X), [1,2,3], Ys).
Ys = [2,4,6]
yes

Currying wird ebenfalls unterstützt. Das obige Beispiel kann wie folgt geschrieben werden:

| ?- meta::map([X]>>([Y]>>(Y is 2*X)), [1,2,3], Ys).
Ys = [2,4,6]
yes

Visual Prolog[edit]

Anonyme Funktionen (im Allgemeinen anonym Prädikate) wurden in Visual Prolog in Version 7.2 eingeführt.[40] Anonyme Prädikate können Werte aus dem Kontext erfassen. Wenn es in einem Objektelement erstellt wurde, kann es auch auf den Objektstatus zugreifen (durch Erfassen This).

mkAdder Gibt eine anonyme Funktion zurück, die das Argument erfasst hat X in der Schließung. Die zurückgegebene Funktion ist eine Funktion, die hinzugefügt wird X zu seinem Argument:

clauses
    mkAdder(X) = { (Y) = X+Y }.

Python[edit]

Python unterstützt einfache anonyme Funktionen über das Lambda-Formular.[28] Der ausführbare Textkörper des Lambda muss ein Ausdruck sein und darf keine Anweisung sein. Dies ist eine Einschränkung, die seine Nützlichkeit einschränkt. Der vom Lambda zurückgegebene Wert ist der Wert des enthaltenen Ausdrucks. Lambda-Formen können überall dort verwendet werden, wo gewöhnliche Funktionen möglich sind. Diese Einschränkungen machen es jedoch zu einer sehr eingeschränkten Version einer normalen Funktion. Hier ist ein Beispiel:

>>> foo = lambda x: x * x
>>> print(foo(10))
100

Im Allgemeinen empfiehlt die Python-Konvention die Verwendung benannter Funktionen, die im selben Bereich definiert sind, wie normalerweise anonyme Funktionen in anderen Sprachen verwendet werden. Dies ist akzeptabel, da lokal definierte Funktionen die volle Leistung von Verschlüssen implementieren und fast so effizient sind wie die Verwendung eines Lambda in Python. In diesem Beispiel kann gesagt werden, dass die eingebaute Leistungsfunktion Curry ist:

>>> def make_pow(n):
...     def fixed_exponent_pow(x):
...         return pow(x, n)
...     return fixed_exponent_pow
...
>>> sqr = make_pow(2)
>>> print (sqr(10))
100
>>> cub = make_pow(3)
>>> print (cub(10))
1000

R.[edit]

In R werden die anonymen Funktionen anhand der Syntax definiert function(argument-list)expression .

> f  function(x)x*x; f(8)
[1] 64
> (function(x,y)x+y)(5,6)
[1] 11

Raku[edit]

In Raku sind alle Blöcke (auch diejenigen, die mit if, while usw. verknüpft sind) anonyme Funktionen. Ein Block, der nicht als Wert verwendet wird, wird sofort ausgeführt.

  1. vollständig anonym, als erstellt bezeichnet
  2. einer Variablen zugeordnet
    my $squarer1 = -> $x { $x * $x };             # 2a. pointy block
    my $squarer2 = { $^x * $^x };                 # 2b. twigil
    my $squarer3 = { my $x = shift @_; $x * $x }; # 2c. Perl 5 style
    
  3. Curry
    sub add ($m, $n) { $m + $n }
    my $seven   = add(3, 4);
    my $add_one = &add.assuming(m => 1);
    my $eight   = $add_one($seven);
    
  4. WhateverCode-Objekt
    my $w = * - 1;       # WhateverCode object
    my $b = { $_ - 1 };  # same functionality, but as Callable block
    

Rubin[edit]

Ruby unterstützt anonyme Funktionen mithilfe einer syntaktischen Struktur namens Block. In Ruby gibt es zwei Datentypen für Blöcke. Procs verhalten sich ähnlich wie Verschlüsse, wohingegen lambdas verhalten sich analog zu einer anonymen Funktion.[41] Bei der Übergabe an eine Methode wird ein Block unter bestimmten Umständen in einen Proc konvertiert.

irb(main):001:0> # Example 1:
irb(main):002:0* # Purely anonymous functions using blocks.
irb(main):003:0* ex = [16.2, 24.1, 48.3, 32.4, 8.5]
=> [16.2, 24.1, 48.3, 32.4, 8.5]
irb(main):004:0> ex.sort_by { |x| x - x.to_i } # Sort by fractional part, ignoring integer part.
=> [24.1, 16.2, 48.3, 32.4, 8.5]
irb(main):005:0> # Example 2:
irb(main):006:0* # First-class functions as an explicit object of Proc -
irb(main):007:0* ex = Proc.new { puts "Hello, world!" }
=> #
irb(main):008:0> ex.call
Hello, world!
=> nil
irb(main):009:0> # Example 3:
irb(main):010:0* # Function that returns lambda function object with parameters
irb(main):011:0* def is_multiple_of(n)
irb(main):012:1>   lambda{|x| x % n == 0}
irb(main):013:1> end
=> nil
irb(main):014:0> multiple_four = is_multiple_of(4)
=> #
irb(main):015:0> multiple_four.call(16)
=> true
irb(main):016:0> multiple_four[15]
=> false

Rost[edit]

In Rust werden anonyme Funktionen als Verschlüsse bezeichnet.[42] Sie werden mit der folgenden Syntax definiert:

|<parameter-name>: <type>| -> <return-type> { <body> };

Zum Beispiel:

let f = |x: i32| -> i32 { x * 2 };

Mit der Typinferenz kann der Compiler jedoch den Typ jedes Parameters und den Rückgabetyp ableiten, sodass das obige Formular wie folgt geschrieben werden kann:

Bei Verschlüssen mit einem einzelnen Ausdruck (dh einem Körper mit einer Linie) können die geschweiften Klammern weggelassen werden:

Abschlüsse ohne Eingabeparameter werden wie folgt geschrieben:

let f = || println!("Hello, world!");

Abschlüsse können als Eingabeparameter von Funktionen übergeben werden, die einen Funktionszeiger erwarten:

// A function which takes a function pointer as an argument and calls it with
// the value `5`.
fn apply(f: fn(i32) -> i32) -> i32 {
    // No semicolon to indicate an implicit return
    f(5)
}

fn main() {
    // Defining the closure
    let f = |x| x * 2;

    println!("{}", apply(f));  // 10
    println!("{}", f(5));      // 10
}

Es kann jedoch komplexe Regeln erfordern, um zu beschreiben, wie Werte im Körper des Verschlusses erfasst werden. Sie werden mit dem implementiert Fn, FnMut, und FnOnce Züge:[43]

  • Fn: Der Verschluss wird durch Bezugnahme erfasst (&T). Sie werden für Funktionen verwendet, die noch aufgerufen werden können, wenn sie nur Referenzzugriff haben (mit &) zu ihrer Umgebung.
  • FnMut: Der Verschluss wird durch veränderliche Referenz erfasst (&mut T). Sie werden für Funktionen verwendet, die aufgerufen werden können, wenn sie einen veränderlichen Referenzzugriff haben (mit &mut) zu ihrer Umgebung.
  • FnOnce: Der Abschluss erfasst nach Wert (T). Sie werden für Funktionen verwendet, die nur einmal aufgerufen werden.

Mit diesen Merkmalen erfasst der Compiler Variablen auf möglichst restriktive Weise.[44] Sie helfen dabei, zu steuern, wie Werte zwischen Bereichen verschoben werden. Dies ist besonders wichtig, da Rust einem lebenslangen Konstrukt folgt, um sicherzustellen, dass Werte “ausgeliehen” und auf vorhersehbare und explizite Weise verschoben werden.[45]

Das Folgende zeigt, wie man einen Abschluss als Eingabeparameter mit dem übergeben kann Fn Merkmal:

// A function that takes a value of type F (which is defined as
// a generic type that implements the `Fn` trait, e.g. a closure)
// and calls it with the value `5`.
fn apply_by_ref<F>(f: F) -> i32
    where F: Fn(i32) -> i32
{
    f(5)
}

fn main() {
    let f = |x| {
        println!("I got the value: {}", x);
        x * 2
    };
    
    // Applies the function before printing its return value
    println!("5 * 2 = {}", apply_by_ref(f));
}

// ~~ Program output ~~
// I got the value: 5
// 5 * 2 = 10

Scala[edit]

In Scala verwenden anonyme Funktionen die folgende Syntax:[46]

(x: Int, y: Int) => x + y

In bestimmten Kontexten, z. B. wenn eine anonyme Funktion ein Parameter ist, der an eine andere Funktion übergeben wird, kann der Compiler auf die Parametertypen der anonymen Funktion schließen und diese in der Syntax weglassen. In solchen Kontexten ist es auch möglich, eine Abkürzung für anonyme Funktionen zu verwenden, indem der Unterstrich verwendet wird, um unbenannte Parameter einzuführen.

val list = List(1, 2, 3, 4)
list.reduceLeft( (x, y) => x + y ) 
// Here, the compiler can infer that the types of x and y are both Int. 
// Thus, it needs no type annotations on the parameters of the anonymous function.

list.reduceLeft( _ + _ )   
// Each underscore stands for a new unnamed parameter in the anonymous function. 
// This results in an even shorter equivalent to the anonymous function above.

Smalltalk[edit]

In Smalltalk werden anonyme Funktionen als Blöcke bezeichnet und durch Senden einer “Wert” -Nachricht aufgerufen (aufgerufen). Wenn Argumente übergeben werden sollen, muss eine Nachricht “value: … value:” mit einer entsprechenden Anzahl von Wertargumenten verwendet werden.

[:x | x*x ] value: 4
"returns 16"

Smalltalk-Blöcke sind technisch gesehen Verschlüsse, die es ihnen ermöglichen, ihren Definitionsbereich zu überleben und dennoch auf die darin deklarierten Variablen zu verweisen.

[:a |
    [:n | a + n ] 
] value: 10
"returns the inner block, which adds 10 to its argument."

Schnell[edit]

In Swift werden anonyme Funktionen als Schließungen bezeichnet.[47] Die Syntax hat folgende Form:

{ (parameters) -> returnType in
  statement
}

Zum Beispiel:

{ (s1: String, s2: String) -> Bool in
  return s1 > s2
}

Der Kürze und Aussagekraft halber können die Parametertypen und der Rückgabetyp weggelassen werden, wenn auf diese geschlossen werden kann:

{ s1, s2 in return s1 > s2 }

In ähnlicher Weise unterstützt Swift auch implizite Rückgabeanweisungen für Abschlüsse mit einer Anweisung:

Schließlich können auch die Parameternamen weggelassen werden. Wenn sie weggelassen werden, werden die Parameter mit Kurzargumentnamen referenziert, die aus dem $ -Symbol gefolgt von ihrer Position bestehen (z. B. $ 0, $ 1, $ 2 usw.):

Tcl[edit]

In Tcl sieht die Anwendung der anonymen Quadrierungsfunktion auf 2 wie folgt aus:[48]

apply {x {expr {$x*$x}}} 2
# returns 4

Dieses Beispiel beinhaltet zwei Kandidaten für das, was es bedeutet, ein zu sein Funktion in Tcl. Das allgemeinste wird normalerweise als a bezeichnet Befehlspräfixund wenn die Variable f hält eine solche Funktion, dann die Art und Weise, die Funktionsanwendung auszuführen f((x) wäre

wo {*} ist das Erweiterungspräfix (neu in Tcl 8.5). Das Befehlspräfix im obigen Beispiel lautet “Anwenden” {x {expr {$x*$x}}}
Befehlsnamen können mit dem Befehl an Präfixe gebunden werden interp alias Befehl. Befehlspräfixe unterstützen das Currying. Befehlspräfixe sind in Tcl-APIs sehr verbreitet.

Der andere Kandidat für “Funktion” in Tcl wird normalerweise als a bezeichnet Lambdaund erscheint als {x {expr {$x*$x}}} Teil des obigen Beispiels. Dies ist der Teil, der die kompilierte Form der anonymen Funktion zwischenspeichert, aber nur durch Übergabe an die Funktion aufgerufen werden kann apply Befehl. Lambdas unterstützen kein Curry, es sei denn, sie werden mit einem gepaart apply um ein Befehlspräfix zu bilden. Lambdas sind in Tcl-APIs selten.

Visual Basic .NET[edit]

In Visual Basic .NET 2008 wurden anonyme Funktionen über das Lambda-Formular eingeführt. In Kombination mit impliziter Typisierung bietet VB eine wirtschaftliche Syntax für anonyme Funktionen. Wie bei Python müssen in VB.NET anonyme Funktionen in einer Zeile definiert werden. Sie können keine zusammengesetzten Aussagen sein. Außerdem muss eine anonyme Funktion in VB.NET wirklich ein VB.NET sein Function – Es muss einen Wert zurückgeben.

Dim foo = Function(x) x * x
Console.WriteLine(foo(10))

Visual Basic.NET 2010 hat Unterstützung für mehrzeilige Lambda-Ausdrücke und anonyme Funktionen ohne Rückgabewert hinzugefügt. Zum Beispiel eine Funktion zur Verwendung in einem Thread.

Dim t As New System.Threading.Thread(Sub ()
                                         For n As Integer = 0 To 10   'Count to 10
                                             Console.WriteLine(n)     'Print each number
                                         Next
                                     End Sub
                                     )
t.Start()

Siehe auch[edit]

Verweise[edit]

  1. ^ “Funktionen höherer Ordnung”. learnyouahaskell.com. Abgerufen 3. Dezember 2014.
  2. ^ Fernandez, Maribel (2009), Rechenmodelle: Eine Einführung in die Berechenbarkeitstheorie, Bachelor-Themen in Informatik, Springer Science & Business Media, p. 33, ISBN 9781848824348, Der Lambda-Kalkül … wurde in den 1930er Jahren von der Alonzo-Kirche als präzise Notation für eine Theorie anonymer Funktionen eingeführt
  3. ^ “Bash Lambda”. 2019-03-08.
  4. ^ BillWagner. “Lambda-Ausdrücke – C # -Referenz”. docs.microsoft.com. Abgerufen 2020-11-24.
  5. ^ “Schließungsunterstützung”. Archiviert von das Original am 06.01.2014. Abgerufen 05.01.2014.
  6. ^ “Was ist neu in ColdFusion 10?”. Archiviert von das Original am 06.01.2014. Abgerufen 05.01.2014.
  7. ^ “Verwaltete COBOL-Referenz”. Mikrofokus-Dokumentation. Mikrofokus. Abgerufen 25. Februar 2014.
  8. ^ ein b “Eine Tour durch die Dartsprache”. dart.dev. Abgerufen 2020-11-24.
  9. ^ “Anonyme Methoden in Delphi – RAD Studio”. docwiki.embarcadero.com. Abgerufen 2020-11-24.
  10. ^ ein b “Erlang / Elixir-Syntax: Ein Crashkurs”. elixir-lang.github.com. Abgerufen 2020-11-24.
  11. ^ ein b “Erlang – Spaß”. erlang.org. Abgerufen 2020-11-24.
  12. ^ ein b Cartermp. “Lambda Expressions: Das lustige Schlüsselwort – F #”. docs.microsoft.com. Abgerufen 2020-11-24.
  13. ^ “Zitate – Faktordokumentation”. Abgerufen 26. Dezember 2015. Ein Zitat ist eine anonyme Funktion (ein Wert, der einen Codeausschnitt bezeichnet), die als Wert verwendet und mit den Fundamental Combinators aufgerufen werden kann.
  14. ^ “Frink”. frinklang.org. Abgerufen 2020-11-24.
  15. ^ ein b “Anonyme Funktionen in GoLang”. GoLang Docs. Abgerufen 2020-11-24.
  16. ^ “Gosu-Dokumentation” (PDF). Abgerufen 4. März 2013.
  17. ^ “Groovy Documentation”. Archiviert von das Original am 22. Mai 2012. Abgerufen 29. Mai 2012.
  18. ^ “Funktionen · Die Julia-Sprache”. docs.julialang.org. Abgerufen 2020-11-24.
  19. ^ “Funktionen höherer Ordnung und Lambdas – Kotlin-Programmiersprache”. Kotlin. Abgerufen 2020-11-24.
  20. ^ “Programmieren in Lua: 6”. www.lua.org. Abgerufen 2020-11-24.
  21. ^ “Maple Programming: 1.6: Anonyme Funktionen und Ausdrücke – Application Center”. www.maplesoft.com. Abgerufen 2020-11-24.
  22. ^ “Maxima 5.17.1 Handbuch: 39. Funktionsdefinition”. maths.cnam.fr. Abgerufen 2020-11-24.
  23. ^ “Nim Manual, Anonymous Procs”.
  24. ^ “Codebeispiele – OCaml”. ocaml.org. Abgerufen 2020-11-24.
  25. ^ “GNU Octave: Anonyme Funktionen”. octave.org. Abgerufen 2020-11-24.
  26. ^ ein b “perlsub – Perl-Unterprogramme – Perldoc-Browser”. perldoc.perl.org. Abgerufen 2020-11-24.
  27. ^ “PHP: Anonyme Funktionen – Handbuch”. www.php.net. Abgerufen 2020-11-24.
  28. ^ ein b “6. Ausdrücke – Python 3.9.0-Dokumentation”. docs.python.org. Abgerufen 2020-11-24.
  29. ^ “4.4 Funktionen: Lambda”. docs.racket-lang.org. Abgerufen 2020-11-24.
  30. ^ ein b “Projekte / Vala / Tutorial – GNOME Wiki!”. wiki.gnome.org. Abgerufen 2020-11-24.
  31. ^ Järvi, Jaakko; Powell, Gary (nd). “Kapitel 16. Boost.Lambda”. Boost-Dokumentation. Boost. Abgerufen 22. Dezember 2014.
  32. ^ C # 4.0-Sprachspezifikation, Abschnitt 5.3.3.29
  33. ^ “Was ist neu in JDK 8?”.
  34. ^ ein b Die Java-Tutorials: Lambda-Ausdrücke, docs.oracle.com
  35. ^ “Programmieren in Lua – Mehr über Funktionen”. Archiviert vom Original am 14. Mai 2008. Abgerufen 2008-04-25.
  36. ^ https://www.cs.cornell.edu/courses/cs3110/2019sp/textbook/basics/anonymous_functions.html
  37. ^ https://nim-lang.github.io/Nim/manual.html#procedures-anonymous-procs
  38. ^ http://php.net/create_function Der obere Rand der Seite zeigt dies mit “(PHP 4> = 4.0.1, PHP 5)” an.
  39. ^ “PHP: rfc: Verschlüsse”.
  40. ^ “Anonyme Prädikate”. in der Visual Prolog-Sprachreferenz
  41. ^ Sosinski, Robert (21.12.2008). “Ruby Blocks, Procs und Lambdas verstehen”. Reactive.IO. Archiviert von das Original am 31.05.2014. Abgerufen 2014-05-30.
  42. ^ “Verschlüsse – Rost am Beispiel”.
  43. ^ “Als Eingabeparameter – Rost am Beispiel”.
  44. ^ “Als Eingabeparameter – Rost am Beispiel”.
  45. ^ “Lebensdauern – Rost am Beispiel”.
  46. ^ “Anonyme Funktionssyntax – Scala-Dokumentation”. Archiviert von das Original am 23.07.2013. Abgerufen 2010-12-31.
  47. ^ “Die Swift-Programmiersprache (Swift 3.0.1): Closures”.
  48. ^ Handbuchseite anwenden, abgerufen am 06.09.2012.

Externe Links[edit]