Quelqu'un pourrait-il expliquer? Je comprends les concepts de base derrière eux mais je les vois souvent utilisés de façon interchangeable et je suis confus.
Et maintenant que nous sommes ici, en quoi diffèrent-ils d'une fonction régulière?
Quelqu'un pourrait-il expliquer? Je comprends les concepts de base derrière eux mais je les vois souvent utilisés de façon interchangeable et je suis confus.
Et maintenant que nous sommes ici, en quoi diffèrent-ils d'une fonction régulière?
Un lambda est juste une fonction anonyme - une fonction définie sans nom. Dans certaines langues, comme le Régime, ils sont équivalents à des fonctions nommées. En fait, la définition de la fonction est re-écrite que la liaison d'un lambda à une variable interne. Dans d'autres langues, comme le Python, il y a quelques (plutôt inutile) les distinctions entre eux, mais ils se comportent de la même manière autrement.
Une fermeture est une fonction quelconque qui se ferme sur l' environnement dans lequel il a été défini. Cela signifie qu'il peut accéder à des variables n'est pas dans sa liste de paramètres. Exemples:
def func(): return h
def anotherfunc(h):
return func()
Cela provoquerait une erreur, car func
ne pas fermer sur l'environnement en anotherfunc
- h
n'est pas défini. func
seulement se ferme sur l'environnement mondial. Cela va fonctionner:
def anotherfunc(h):
def func(): return h
return func()
Parce qu'ici, en func
est définie en anotherfunc
, et en python 2.3 et supérieur (ou un certain nombre de ce genre) quand ils ont presque eu des fermetures de corriger (mutation ne fonctionne toujours pas), cela signifie qu'il se referme sur anotherfunc
s'environnement et peuvent accéder à des variables à l'intérieur d'elle. En Python 3.1+, la mutation fonctionne aussi lors de l'utilisation de l' nonlocal
mot-clé.
Un autre point important - func
continuera à se fermer sur anotherfunc
s'environnement, même lorsqu'il n'est plus évalué dans le cadre d' anotherfunc
. Ce code fonctionnera également:
def anotherfunc(h):
def func(): return h
return func
print anotherfunc(10)()
Cela permettra d'imprimer 10.
Ceci, comme vous le remarquez, n'a rien à voir avec lambda's - ils sont deux différents (bien que relative) des concepts.
Quand la plupart des gens pensent de fonctions, ils pensent à des fonctions nommées:
function foo() { return "This string is returned from the 'foo' function"; }
Ceux-ci sont appelés par leur nom, bien sûr:
foo(); //returns the string above
Avec les expressions lambda, vous pouvez avoir les fonctions anonymes:
@foo = lambda() {return "This is returned from a function without a name";}
Avec l'exemple ci-dessus, vous pouvez appeler le lambda par le biais de la variable, il a été attribué à:
foo();
Plus utile que d'attribuer des fonctions anonymes pour les variables, cependant, sont les passant à ou de fonctions d'ordre supérieur, c'est à dire, les fonctions qui acceptent/retour d'autres fonctions. Dans beaucoup de ces cas, la dénomination d'une fonction est inutile:
function filter(list, predicate)
{ @filteredList = [];
for-each (@x in list) if (predicate(x)) filteredList.add(x);
return filteredList;
}
//filter for even numbers
filter([0,1,2,3,4,5,6], lambda(x) {return (x mod 2 == 0)});
Une clôture peut être un nom ou la fonction anonyme, mais il est connu en tant que tel lorsqu'il "se ferme sur" les variables dans le champ d'application où la fonction est définie, c'est à dire, la fermeture de toujours se référer à l'environnement avec l'variables qui sont utilisées dans la fermeture elle-même. Voici un nommé fermeture:
@x = 0;
function incrementX() { x = x + 1;}
incrementX(); // x now equals 1
Cela ne veut pas sembler beaucoup, mais si c'était dans une autre fonction et que vous avez passé incrementX
à une fonction externe?
function foo()
{ @x = 0;
function incrementX()
{ x = x + 1;
return x;
}
return incrementX;
}
@y = foo(); // y = closure of incrementX over foo.x
y(); //returns 1 (y.x == 0 + 1)
y(); //returns 2 (y.x == 1 + 1)
C'est de cette façon, vous obtenez des objets ayant dans la programmation fonctionnelle. Depuis appellation "incrementX" n'est pas nécessaire, vous pouvez utiliser une lambda dans ce cas:
function foo()
{ @x = 0;
return lambda()
{ x = x + 1;
return x;
};
}
Pas toutes les fermetures sont en lambdas et pas toutes les expressions lambda sont des fermetures. Les deux sont des fonctions, mais pas nécessairement de la manière dont nous avons l'habitude de connaître.
Un lambda est essentiellement une fonction qui est définie en ligne plutôt que la méthode standard de déclarer les fonctions. Les Lambdas peuvent souvent être passé autour comme des objets.
Une fermeture est une fonction qui enferme ses environs état par la référence à des champs extérieurs à son corps. Le clos de l'état de vestiges à travers les invocations de la fermeture.
Dans un langage orienté-objet, les fermetures sont normalement fournis par les objets. Cependant, certains langages à objets (par exemple, C#) de mettre en œuvre une fonctionnalité spéciale, qui est plus proche de la définition de fermetures fournis uniquement par des langages fonctionnels (tels que lisp) qui n'ont pas d'objets de joindre l'état.
Ce qui est intéressant, c'est que l'introduction de Lambdas et des Fermetures en C# apporte de la programmation fonctionnelle plus près à intégrer l'utilisation.
C'est aussi simple que cela: lambda est une structure du langage, c'est à dire tout simplement la syntaxe pour les fonctions anonymes; une fermeture est une technique à mettre en œuvre-ou de toute première classe de fonctions, pour que la matière, nommés ou anonymes.
Plus précisément, une clôture est de savoir comment un de première classe de la fonction est représentée au moment de l'exécution, comme une paire de son "code" et à un environnement "fermeture" sur tous les non-les variables locales utilisées dans ce code. De cette façon, ces variables sont toujours accessibles, même lorsque les étendues extérieures où ils proviennent ont déjà été abandonnées.
Malheureusement, il y a beaucoup de langues qui n'ont pas de fonctions de soutien comme des valeurs de première classe, ou seulement de les soutenir dans paralysé forme. Donc, les gens utilisent souvent le terme "fermeture" pour le distinguer de "la vraie chose".
Du point de vue des langages de programmation, ils sont totalement deux choses différentes.
En gros pour un de Turing complet de la langue, nous avons seulement besoin de très peu d'éléments, par exemple, de l'abstraction, de l'application et de la réduction. L'Abstraction et l'application fournit la façon dont vous pouvez construire jusqu'lamdba expression, et la réduction dertermines le sens de l'expression lambda.
Lambda fournit un moyen vous pouvez résumé le processus de calcul. par exemple, pour calculer la somme de deux nombres, un processus qui prend deux paramètres x, y et retourne x+y peut être abstrait. Dans le schéma, vous pouvez l'écrire comme
(lambda (x y) (+ x y))
Vous pouvez renommer les paramètres, mais la tâche qu'il accomplit ne change pas. Dans presque tous les langages de programmation, vous pouvez donner l'expression lambda un nom, qui sont des fonctions nommées. Mais il n'y a pas beaucoup de différence, ils peuvent être conceptuellement considéré comme juste la syntaxe de sucre.
OK, maintenant, imaginez comment cela peut être mis en œuvre. Chaque fois que nous appliquons l'expression lambda pour certaines expressions, par exemple
((lambda (x y) (+ x y)) 2 3)
On peut tout simplement remplacer les paramètres de l'évaluation de l'expression. Ce modèle est déjà très puissant. Mais ce modèle n'est pas nous permettre de modifier les valeurs des symboles, par exemple, Nous ne pouvons pas imiter le changement de statut. Donc nous avons besoin d'un modèle plus complexe. Pour faire court, chaque fois que nous voulons calculer le sens de l'expression lambda, nous avons mis la paire de symbole et la valeur correspondante dans un environnement(ou la table). Puis le reste (+ x y) est évaluée par la recherche de la symboles correspondants dans la table. Maintenant, si nous fournir certaines primitives pour fonctionner sur l'environnement directement, nous pouvons modéliser les changements de statut!
Avec cet arrière-plan, cochez cette fonction:
(lambda (x y) (+ x y z))
Nous savons que lorsque nous évaluons l'expression lambda, x y sera lié dans une nouvelle table. Mais comment et où pouvons-nous regarder à z? En fait z est appelée une variable libre. Il doit y avoir un extérieur un environnement qui contient z. Sinon le sens de l'expression ne peut pas être déterminée que par la liaison de x et y. Pour être plus clair, vous pouvez écrire quelque chose comme suit dans le schéma:
((lambda (z) (lambda (x y) (+ x y z))) 1)
Donc z serait lié à 1 dans une table externe. Nous obtenons toujours une fonction qui accepte deux paramètres, mais le vrai sens il dépend aussi de l'environnement extérieur. En d'autres termes l'environnement extérieur se ferme sur les variables libres. Avec l'aide de jeu!, nous pouvons faire la fonction dynamique, j'.e, ce n'est pas une fonction au sens mathématique. De quoi il en retourne ne dépend pas seulement de l'entrée, mais z ainsi.
C'est quelque chose que vous connaissez déjà très bien, une méthode d'objets presque toujours s'appuie sur l'état des objets. C'est pourquoi certaines personnes disent "les fermetures sont pauvre homme d'objets. "Mais on pourrait également envisager les objets comme du pauvre fermetures depuis on a vraiment l'impression de la première classe de fonctions.
J'ai utiliser le schéma pour illustrer les idées en raison de ce régime est l'un des plus anciens de la langue qui a une réelle fermetures. Tous les matériaux sont beaucoup mieux présentés dans SICP chapitre 3.
Pour résumer, lambda et la fermeture sont vraiment différents concepts. Un lambda est une fonction. Une fermeture est une paire de lambda et le correspondant de l'environnement, qui ferme le lambda.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.