Question Qu'est-ce qu'un lambda (fonction)?


Pour une personne sans antécédents comp-sci, qu'est-ce qu'un lambda dans le monde de l'informatique?


619
2017-08-19 16:20


origine


Réponses:


Lambda vient du Lambda Calculus et fait référence à des fonctions anonymes dans la programmation.

Pourquoi est-ce cool? Il vous permet d'écrire rapidement des fonctions sans les nommer. C'est aussi un bon moyen d'écrire des fermetures. Avec ce pouvoir, vous pouvez faire des choses comme ça.

Python

def adder(x):
    return lambda y: x + y
add5 = adder(5)
add5(1)
6

Comme vous pouvez le voir dans l'extrait de Python, l'additionneur de fonctions prend un argument x, et renvoie une fonction anonyme, ou lambda, qui prend un autre argument y. Cette fonction anonyme vous permet de créer des fonctions à partir de fonctions. Ceci est un exemple simple, mais il devrait transmettre le pouvoir des lambdas et des fermetures.

Exemples dans d'autres langues

JavaScript

var adder = function (x) {
    return function (y) {
        return x + y;
    };
};
add5 = adder(5);
add5(1) == 6

JavaScript (ES6)

const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6

Schème

(define adder
    (lambda (x)
        (lambda (y)
           (+ x y))))
(define add5
    (adder 5))
(add5 1)
6

C # 3.5 ou supérieur

Func<int, Func<int, int>> adder = 
    (int x) => (int y) => x + y; // `int` declarations optional
Func<int, int> add5 = adder(5);
var add6 = adder(6); // Using implicit typing
Debug.Assert(add5(1) == 6);
Debug.Assert(add6(-1) == 5);

// Closure example
int yEnclosed = 1;
Func<int, int> addWithClosure = 
    (x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);

Rapide

func adder(x: Int) -> (Int) -> Int{
   return { y in x + y }
}
let add5 = adder(5)
add5(1)
6

PHP

$a = 1;
$b = 2;

$lambda = function () use (&$a, &$b) {
    echo $a + $b;
};

echo $lambda();

Haskell

(\x y -> x + y) 

Java voir ce post

// The following is an example of Predicate : 
// a functional interface that takes an argument 
// and returns a boolean primitive type.

Predicate<Integer> pred = x -> x % 2 == 0; // Tests if the parameter is even.
boolean result = pred.test(4); // true

Lua

adder = function(x)
    return function(y)
        return x + y
    end
end
add5 = adder(5)
add5(1) == 6        -- true

932
2017-08-19 16:27



Un lambda est un type de fonction, défini en ligne. Avec un lambda, vous avez également une sorte de type variable qui peut contenir une référence à une fonction, lambda ou autre.

Par exemple, voici un morceau de code C # qui n'utilise pas de lambda:

public Int32 Add(Int32 a, Int32 b)
{
    return a + b;
}

public Int32 Sub(Int32 a, Int32 b)
{
    return a - b;
}

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, Add);
    Calculator(10, 23, Sub);
}

Ceci appelle Calculatrice, en transmettant non seulement deux nombres, mais aussi la méthode à appeler dans Calculatrice pour obtenir les résultats du calcul.

En C # 2.0 nous avons des méthodes anonymes, qui raccourcissent le code ci-dessus pour:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a + b;
    });
    Calculator(10, 23, delegate(Int32 a, Int32 b)
    {
        return a - b;
    });
}

Et puis en C # 3.0 nous avons obtenu lambdas qui rend le code encore plus court:

public delegate Int32 Op(Int32 a, Int32 b);

public void Calculator(Int32 a, Int32 b, Op op)
{
    Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}

public void Test()
{
    Calculator(10, 23, (a, b) => a + b);
    Calculator(10, 23, (a, b) => a - b);
}

96
2017-08-19 16:27



Ça fait référence à calcul lambda, qui est un système formel qui a juste des expressions lambda, qui représentent une fonction qui prend une fonction pour son unique argument et retourne une fonction. Toutes les fonctions du calcul lambda sont de ce type, c'est-à-dire λ : λ → λ.

Lisp a utilisé le concept lambda pour nommer ses littéraux de fonction anonymes. Ce lambda représente une fonction qui prend deux arguments, x et y, et renvoie leur produit:

(lambda (x y) (* x y)) 

Il peut être appliqué en ligne comme ceci (évalue à 50):

((lambda (x y) (* x y)) 5 10)

54
2017-08-19 16:23



Le nom "lambda" est juste un artefact historique. Tout ce dont nous parlons est une expression dont la valeur est une fonction.

Un exemple simple (en utilisant Scala pour la ligne suivante) est:

args.foreach(arg => println(arg))

où l'argument de la foreach method est une expression pour une fonction anonyme. La ligne ci-dessus est plus ou moins la même chose que d'écrire quelque chose comme ça (pas tout à fait vrai code, mais vous aurez l'idée):

void printThat(Object that) {
  println(that)
}
...
args.foreach(printThat)

sauf que vous n'avez pas besoin de vous embêter avec:

  1. Déclarer la fonction ailleurs (et devoir la rechercher lorsque vous reviendrez le code plus tard).
  2. Nommer quelque chose que vous utilisez seulement une fois.

Une fois que vous avez l'habitude de travailler sur des valeurs, le fait d'en avoir besoin semble aussi bête que d'être obligé de nommer chaque expression, par exemple:

int tempVar = 2 * a + b
...
println(tempVar)

au lieu d'écrire simplement l'expression là où vous en avez besoin:

println(2 * a + b)

La notation exacte varie d'une langue à l'autre; Le grec n'est pas toujours requis! ;-)


48
2017-08-29 18:36



Le lambda-calcul est une théorie mathématique cohérente de la substitution. En mathématiques scolaires on voit par exemple x+y=5 jumelé avec x−y=1. En plus des moyens de manipuler des équations individuelles, il est également possible de rassembler les informations de ces deux éléments, à condition que les substitutions d'équations croisées soient effectuées logiquement. Le calcul lambda codifie la manière correcte de faire ces substitutions.

Étant donné que y = x−1 est un réarrangement valide de la deuxième équation, ceci: λ y = x−1 désigne une fonction remplaçant les symboles x−1 pour le symbole y. Maintenant, imaginez appliquer λ y à chaque terme dans la première équation. Si un terme est y puis effectuez la substitution; sinon ne fais rien. Si vous le faites sur papier, vous verrez comment appliquer cette λ y rendra la première équation solvable.

C'est une réponse sans aucune science informatique ou programmation.

L'exemple de programmation le plus simple que je puisse penser vient de http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works:

voici comment la fonction de carré pourrait être définie dans un impératif   langage de programmation (C):

int square(int x)
{
    return x * x;
}

La variable x est un paramètre formel qui est remplacé par le réel   valeur à mettre au carré lorsque la fonction est appelée. Dans un fonctionnel   langue (Scheme) la même fonction serait définie:

(define square
  (lambda (x) 
    (* x x)))

Ceci est différent de plusieurs façons, mais il utilise toujours le paramètre formel   x de la même manière.


Ajoutée:  http://imgur.com/a/XBHub

lambda


37
2017-08-14 03:00



Légèrement simplifié: une fonction lambda peut être transmise à d'autres fonctions et sa logique est accessible.

En C # lambda, la syntaxe est souvent compilée avec des méthodes simples de la même manière que les délégués anonymes, mais elle peut aussi être décomposée et sa logique lue.

Par exemple (en C # 3):

LinqToSqlContext.Where( 
    row => row.FieldName > 15 );

LinqToSql peut lire cette fonction (x> 15) et la convertir en SQL réel pour l'exécuter à l'aide d'arborescences d'expression.

La déclaration ci-dessus devient:

select ... from [tablename] 
where [FieldName] > 15      --this line was 'read' from the lambda function

Ceci est différent des méthodes normales ou des délégués anonymes (qui sont juste de la magie du compilateur) parce qu'ils ne peuvent pas être lis.

Toutes les méthodes en C # qui utilisent la syntaxe lambda ne peuvent pas être compilées dans des arbres d'expression (c'est-à-dire des fonctions lambda réelles). Par exemple:

LinqToSqlContext.Where( 
    row => SomeComplexCheck( row.FieldName ) );

Maintenant, l'arbre d'expression ne peut pas être lu - SomeComplexCheck ne peut pas être décomposé. L'instruction SQL s'exécutera sans l'où, et chaque ligne dans les données sera mise à travers SomeComplexCheck.

Les fonctions Lambda ne doivent pas être confondues avec les méthodes anonymes. Par exemple:

LinqToSqlContext.Where( 
    delegate ( DataRow row ) { 
        return row.FieldName > 15; 
    } );

Cela a aussi une fonction 'inline', mais cette fois c'est juste de la magie du compilateur - le compilateur C # divisera ceci en une nouvelle méthode d'instance avec un nom autogénéré.

Les méthodes anonymes ne peuvent pas être lues, et donc la logique ne peut pas être traduite comme elle le peut pour les fonctions lambda.


13
2017-08-19 16:30



J'aime l'explication de Lambdas dans cet article: L'évolution de LINQ et son impact sur la conception de C #. Cela m'a semblé logique car cela montre un monde réel pour Lambdas et le construit comme un exemple pratique.

Leur explication rapide: les Lambdas sont un moyen de traiter le code (fonctions) comme des données.


6
2017-08-19 16:29



Un exemple d'un lambda dans Ruby est comme suit:

hello = lambda do
    puts('Hello')
    puts('I am inside a proc')
end

hello.call

Générera la sortie suivante:

Hello
I am inside a proc

6
2017-08-19 17:17



@Brian J'utilise lambdas tout le temps en C #, dans les opérateurs LINQ et non-LINQ. Exemple:

string[] GetCustomerNames(IEnumerable<Customer> customers)
 { return customers.Select(c=>c.Name);
 }

Avant C #, j'ai utilisé des fonctions anonymes en JavaScript pour les rappels aux fonctions AJAX, avant même que le terme Ajax ne soit inventé:

getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/});

La chose intéressante avec la syntaxe lambda de C #, cependant, est que leur propre type ne peut pas être déduit (ie, vous ne pouvez pas taper var foo = (x, y) => x * y) mais en fonction du type qu'ils sont assignés à, ils seront compilés en tant que délégués ou arbres de syntaxe abstraits représentant l'expression (ce qui est la façon dont les mappeurs d'objets LINQ font leur magie "intégrée à la langue").

Lambdas dans LISP peut également être passé à un opérateur de devis, puis parcouru comme une liste de listes. Certaines macros puissantes sont faites de cette façon.


4
2017-08-19 18:25



La question est formellement répondue grandement, donc je ne vais pas essayer d'en ajouter plus à ce sujet.

En très simple, informel mots à quelqu'un qui sait très peu ou rien sur les mathématiques ou la programmation, je l'expliquerais comme une petite "machine" ou "boîte" qui prend un peu d'entrée, fait du travail et produit une sortie, n'a pas de nom particulier, mais nous savons où c'est et par cette seule connaissance, nous l'utilisons.

En pratique, pour une personne qui sait ce qu'est une fonction, je leur dirais que c'est une fonction qui n'a pas de nom, habituellement mise en mémoire qui peut être utilisée simplement en se référant à cette mémoire (généralement via l'utilisation de une variable - s'ils ont entendu parler du concept des pointeurs de fonction, je les utiliserais comme un concept similaire) - cette réponse couvre les jolis éléments de base (aucune mention de fermetures, etc.) mais on peut facilement comprendre le point.


4
2018-01-31 01:24



Vous pouvez le considérer comme une fonction anonyme - voici quelques informations supplémentaires: Wikipedia - Fonction anonyme


3
2017-08-19 16:23