Le lambda calcul est un modèle de calcul inventé par Alonzo Church dans les années 30. La syntaxe et la sémantique de la plupart des langages de programmation fonctionnels sont directement ou indirectement inspirées du calcul lambda.
Le lambda calcul, dans sa forme la plus élémentaire, comporte deux opérations: l’abstraction (création d’une fonction (anonyme)) et l’application (application d’une fonction). L'abstraction est effectuée à l'aide de l'opérateur λ, qui donne son nom au lambda calcul.
- Expressions lambda
- Fonctions Lambda
Les fonctions anonymes sont souvent appelées "lambdas", "fonctions lambda" ou "expressions lambda" car, comme je l’ai dit plus haut, λ était le symbole pour créer des fonctions anonymes dans le calcul lambda (et le mot lambda
est utilisé pour créer des fonctions anonymes dans de nombreux lisp). langues basées sur la même raison).
Ce n'est pas un terme couramment utilisé, mais je suppose que cela signifie une programmation utilisant des fonctions anonymes ou une programmation utilisant des fonctions d'ordre supérieur.
Un peu plus d'informations sur les lambdas dans C ++ 0x, leur motivation et leurs liens avec les pointeurs de fonction (une grande partie de ceci est probablement une répétition de ce que vous savez déjà, mais j'espère que cela aidera à expliquer la motivation des lambdas et leurs différences. des pointeurs de fonction):
Les pointeurs de fonction, qui existaient déjà dans C, sont très utiles pour passer par exemple une fonction de comparaison à une fonction de tri. Cependant, leur utilité est limitée:
Par exemple, si vous souhaitez trier un vecteur de vecteurs par l' i
élément th de chaque vecteur (où i
est un paramètre d'exécution), vous ne pouvez pas résoudre ce problème avec un pointeur de fonction. Une fonction qui compare deux vecteurs par leur i
élément th devrait prendre trois arguments ( i
et les deux vecteurs), mais la fonction de tri nécessiterait une fonction prenant deux arguments. Ce dont nous aurions besoin, c'est d'un moyen de fournir l'argument i
à la fonction avant de le passer à la fonction de tri, mais nous ne pouvons pas le faire avec des fonctions C simples.
Pour résoudre ce problème, C ++ a introduit le concept "d'objets de fonction" ou "foncteurs". Un foncteur est fondamentalement un objet qui a une operator()
méthode. Nous pouvons maintenant définir une classe CompareByIthElement
, qui prend l'argument en i
tant qu'argument constructeur, puis les deux vecteurs à comparer en tant qu'arguments de la operator()
méthode. Pour trier un vecteur de vecteurs par l' i
élément th, nous pouvons maintenant créer un CompareByIthElement
objet avec i
comme argument, puis passer cet objet à la fonction de tri.
Comme les objets fonction ne sont que des objets et non des fonctions techniques (même s'ils sont censés se comporter comme eux), vous ne pouvez pas faire pointer un pointeur de fonction sur un objet fonction (vous pouvez bien sûr avoir un pointeur sur un objet fonction mais aurait un type comme CompareByIthElement*
et ne serait donc pas un pointeur de fonction).
La plupart des fonctions de la bibliothèque standard C ++ qui acceptent des fonctions en tant qu'arguments sont définies à l'aide de modèles afin qu'elles fonctionnent avec des pointeurs de fonction ainsi que des objets fonction.
Passons maintenant à lambdas:
Définir une classe entière à comparer à l'aide du i
troisième élément est un peu détaillé si vous ne l'utilisez qu'une fois pour trier un vecteur. Même dans le cas où vous n'avez besoin que d'un pointeur de fonction, la définition d'une fonction nommée est sous-optimale si elle n'est utilisée qu'une seule fois car a) elle pollue l'espace de noms et b) la fonction sera généralement très petite et il n'y a pas vraiment une bonne raison d'abréger la logique dans sa propre fonction (à part cela, vous ne pouvez pas avoir de pointeur de fonction sans définir une fonction).
Donc, pour réparer ce lambdas ont été introduits. Les Lambdas sont des objets de fonction, pas des pointeurs de fonction. Si vous utilisez un lambda littéral, un [x1, x2](y1,y2){bla}
code similaire à celui-ci est généré:
- Définissez une classe qui a deux variables membres (
x1
et x2
) et une operator()
avec les arguments ( y1
et y2
) et le corps bla
.
- Créez une instance de la classe en définissant les variables membres
x1
et x2
les valeurs des variables x1
et x2
de la portée actuelle.
Ainsi, les lambdas se comportent comme des objets fonction, sauf que vous ne pouvez pas accéder à la classe générée pour implémenter un lambda autrement que par le lambda. En conséquence, toute fonction qui accepte les foncteurs comme arguments (c'est-à-dire toute fonction non C dans la bibliothèque standard) acceptera lambdas, mais aucune fonction n'acceptera que les pointeurs de fonction.