2010-07-21 6 views
5

Qu'est-ce que la fermeture et son exemple de correspondance? J'ai beaucoup de recherches et je ne comprenais pas. Veuillez expliquer l'aspect conceptuel du langage de programmation générique et l'aspect du langage de programmation spécifique.Définition de la fermeture et exemple

Aidez-nous s'il vous plaît.

Merci.

+0

Questions http://stackoverflow.com/questions/36636/what-is-a-closure et http://stackoverflow.com/questions/1095707/what-is-the-exact-definition-of-a- la fermeture est similaire à celle-ci –

Répondre

1

Voici comment je pense à une fermeture ....

Un objet fonction se compose de deux choses. La première chose est le code de la fonction, la seconde est la portée dans laquelle elle s'exécute. Dans une fermeture, l'étendue dans laquelle la fonction s'exécute et le code sont détachés l'un de l'autre. Le même code peut s'exécuter dans une variété d'étendues.

Si cela était autorisé sans restriction, cela entraînerait une grande confusion. Même lorsque c'est quelque chose d'aussi lâche que la portée dynamique (la fonction hérite de la portée de l'endroit d'où elle a été appelée), cela devient très confus.

Les fermetures sont un moyen pratique de spécifier des règles de portée qui ont beaucoup de sens car elles nécessitent seulement de lire le code au lieu de le tracer. Dans une fermeture, la fonction obtient la portée de l'endroit où elle a été déclarée.S'il a été déclaré lors de l'exécution d'une autre fonction, il obtient la portée de cette instance spécifique de la pile de la fonction. C'est beaucoup plus simple et plus facile à comprendre que d'être capable de donner la clôture et la portée arbitraire, ou la portée dynamique.

Voici un exemple d'une fermeture trivial en Python:

def outer(): 
    def closure(): 
     pass 
    return closure 

Ici, la fonction closure est une fermeture. Il n'utilise en fait aucune variable de la portée dans laquelle il a été défini, donc c'est plutôt trivial, mais c'est toujours un.

est ici un pas si trivial, mais la fermeture toujours simple Python:

def outer(x): 
     def closure(): 
      return x 
     return closure 
f1 = outer(5) 
f2 = outer(6) 

appel f1() retournera 5 et appelant f2() retournera 6. Comme vous pouvez le voir, la fonction closure est un code partiel , et la portée de la partie.

Lorsque outer(5) est appelée, elle crée une entrée de pile pour l'appel qui contient une version de la x variable qui contient la valeur 5. Il déclare alors la fonction closure qui obtient cette portée.

Lorsque outer(6) est appelée, elle crée une entrée de pile pour l'appel qui contient une version de la x variable qui contient la valeur 6. Il déclare alors la fonction closure qui obtient cette portée.

+0

Merci pour votre explication – peterwkc

9

Une fermeture est essentiellement une fonction B imbriquée dans une fonction A qui peut accéder à des variables locales A:

function A() { 
    var x = 5; 

    function B() { 
     print(x); 
    } 

    return B; 
} 

Si vous venez d'un c'est fond C++, assez difficile à digérer. Lorsque nous essayons d'appeler la fonction retournée par A, à quoi va-t-il se référer? Est-ce que ce x ne sera pas invalide puisque A() s'est terminé? La réponse est que x vit effectivement. Ce B nous sommes retournés porte effectivement x avec implicitement. Cool, hein?

Dans un sens plus général, une fermeture est une fonction liée à certaines données. Dans un langage sans fermetures comme C, chaque programme a un nombre fixe de fonctions. Avec les fermetures, vous pouvez, en un sens, "créer des fonctions" en les liant à des données dynamiques. Bien sûr, personne ne vous empêche d'imiter les fermetures en C, mais cela peut parfois être douloureux.

Les fermetures sont vraiment utiles. Par exemple, supposons que nous voulons mettre en œuvre notre propre « boucle »:

function loop(count, f) { 
    for (var i = 0; i < count; i++) 
     f(i); 
} 

var array = [0,1,2,3,4]; 

loop(5, function(i) { 
    print(array[i]); 
}); 

être autorisé à accéder à des variables extérieures sans faire un tas de bêtises supplémentaires de garder le code agréable et simple. Sans fermetures, vous pourriez avoir à passer une variable de contexte à la place fonction loop:

function loop(count, f, ctx) { 
    for (var i = 0; i < count; i++) 
     f(i, ctx); 
} 

var array = [0,1,2,3,4]; 

loop(5, function(i, ctx) { 
    print(ctx[i]); 
}, array); 

Un autre exemple: supposons que nous voulons enregistrer un rappel dans jQuery, mais il peut être exécuté longtemps après que la fonction et de son appelant et son l'appelant de l'appelant sont fait en cours d'exécution:

$(document).ready(function(){ 

    var clicked = 0; 

    $('#button').click(function(){ 
     clicked++; 
     alert("You've pressed the button " + clicked + " times."); 
    }); 

}); 

Si JavaScript ont été plus comme C++ (avant C++ 0x), que clicked variable serait révolue depuis longtemps au moment où la fonction donnée à $(document).ready() a été appelée, et le clic de bouton le rappel aurait un comportement indéfini.

+0

Il est intéressant de noter que C++ 0x a maintenant des lambdas qui capturent les variables de leur portée englobante. Ainsi, l'argument "Si vous venez d'un contexte C++" * devient moins pertinent. –

+0

C'est plutôt cool. Merci. – LandonSchropp

+0

@Alexandre Jasmin - Ce sont des formes de fermeture très étranges. Beaucoup plus explicite que la plupart des langues qui les supportent. Bien que j'aime mieux ça. Je pense que vous devriez indiquer les variables que vous avez l'intention d'utiliser dans la portée englobante. – Omnifarious

0

Si vous voulez un exemple sur les fermetures je vous suggère de vérifier le livre

Plongez dans Python: Chapitre 6 - Fermetures & Générateurs

Le livre son & ouvert gratuit et vous pouvez le télécharger à --->http://diveintopython3.org/

L'exemple est intéressant, clair et prend progressivement une approche plus avancée. Pour la première exposition c'est génial je pense.

Jetez un coup d'oeil il n'y a aucune raison de le reproduire ici tant que vous pouvez simplement le télécharger ou le lire en ligne.

Questions connexes