Qu'est-ce qu'un lambda et pourquoi serait-il utile? [fermé]

56

Jusqu'ici j'ai entendu parler de:

  • Lambda calcul
  • Programmation Lambda
  • Expressions lambda
  • Fonctions Lambda

Ce qui tout semble être lié à la programmation fonctionnelle ...

Apparemment, il sera intégré à C ++ 1x, je pourrais donc mieux le comprendre maintenant:

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

Quelqu'un peut-il définir brièvement ce que sont les choses lambdas et donner un endroit où cela peut être utile?

jokoon
la source
2
Notez que la terminologie vient historiquement du fait de vouloir un bon moyen de parler de la fonction représentée par une expression. La fonction représentée par x + 1 est alors écrite lambda x. x + 1.
Kasterma
De manière lambda, une fonction mange une autre fonction et / ou une valeur d'entrée produit une autre fonction. Cela continue jusqu'à ce qu'une fonction produise une solution. En outre, les œufs d'alligator .
SD
C'est du grec pour moi. Je pense que je vais aller avoir un gyroscope, j'aime l'agneau, duh.

Réponses:

44
  • Lambda calcul

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 lambdaest utilisé pour créer des fonctions anonymes dans de nombreux lisp). langues basées sur la même raison).

  • Programmation Lambda

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ù iest 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 ( iet 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 itant 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 CompareByIthElementobjet avec icomme 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 itroisiè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é:

  1. Définissez une classe qui a deux variables membres ( x1et x2) et une operator()avec les arguments ( y1et y2) et le corps bla.
  2. Créez une instance de la classe en définissant les variables membres x1et x2les valeurs des variables x1et x2de 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.

sepp2k
la source
Les fonctions anonymes sont-elles utilisées avec des pointeurs de fonction? Sinon, quelle est la différence ?
jokoon
1
@jokoon: Non, les fonctions anonymes ne peuvent pas être transmises en tant que paramètres à des fonctions qui prennent uniquement des pointeurs de fonction. Cependant, la plupart des fonctions qui prennent des fonctions en tant qu'arguments sont définies à l'aide de modèles, de sorte qu'elles puissent prendre n'importe quel type d'objet de fonction en tant qu'argument, pas seulement un pointeur de fonction. Autrement dit, dans la plupart des endroits où vous pouvez utiliser des pointeurs de fonction ( std::sortpar exemple), vous pourrez utiliser des fonctions anonymes. Cependant, lorsque vous définissez une fonction qui doit prendre une fonction anonyme comme argument, vous devez utiliser un modèle ou std::functionle type de l'argument.
sepp2k
donc un pointeur de fonction ne peut pas contenir de lambda ...
jokoon
1
+1 Excellente explication - Je n'avais pas été en mesure de le savoir non plus.
Michael K
2
Je suis avec Michael à ce sujet. C'est très complet. +1de moi.
sbi
18

Fondamentalement, les fonctions lambda sont des fonctions que vous créez "à la volée". En C ++ 1x, ils pourraient être utilisés pour améliorer sa prise en charge de la programmation fonctionnelle:

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

Cela donnera un code similaire à celui-ci:

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

Si vous n’avez besoin some_functorque de cet appel std::for_each(), la fonction lambda présente plusieurs avantages:

  • ce qui est fait dans la boucle est spécifié là où la fonction de bouclage est appelée
  • cela vous évite d'écrire une partie du code de la plaque de chaudière
  • il n'y a pas de foncteur qui traîne au niveau de l'espace de noms qui fait que tout le monde regarde le code en se demandant à quoi il a besoin
sbi
la source
7

Une fonction lambda est un autre nom pour une fonction anonyme - essentiellement une fonction sans nom.

Habituellement, vous l’utilisez dans des langues où vous n’avez besoin d’utiliser cette fonction qu’une seule fois. Par exemple au lieu de

def add(a, b)
  return a+b

puis en passant cette fonction dans une autre fonction comme si

reduce(add, [5,3,2])

Avec un lambda, vous feriez simplement

reduce(lambda x, y: a+b, [5,3,2])
Martin Konecny
la source