56 votes

Que sont les "funargs à la baisse"?

Jamie Zawinski utilise ce terme dans son (1997) de l'article "java suce" comme si vous devriez savoir ce que cela signifie:

Je déteste vraiment le manque de recul-funargs; anonyme classes sont un piètre substitut. (Je ne peux vivre sans longue durée de vie des fermetures, mais je trouve que l'absence de pointeurs de fonction d'une immense douleur.)

Il semble être Lisper de l'argot, et que j'ai pu trouver la suite brève définition ici, mais de toute façon, je pense que je n'ai toujours pas compris:

De nombreuses fermetures sont utilisés uniquement lors de la mesure de l'liaisons ils se réfèrent; ceux-ci sont connus comme "la baisse funargs" dans le langage Lisp.

Il n'y avait pas de Steve Yegge, je venais de sentir stupide maintenant, mais il semble, il pourrait être OK pour demander:

Jamie Zawinski est un héros. Une légende vivante. [...] Un gars qui peut utiliser le terme "à la baisse funargs" et puis l'éblouissement à vous tout oser vous demander de lui expliquer, mais c'est crétin.

-- XEmacs est morte, vive la XEmacs

Donc, il y a un Lisper ici qui permet de compiler ce pour C-style-programmeurs comme moi?

52voto

Konrad Rudolph Points 231505

Les funargs descendants sont des fonctions locales qui ne sont pas retournées ou qui quittent leur portée de déclaration. Ils ne peuvent être transmis vers le bas à d' autres fonctions de la portée actuelle.

Deux exemples C’est un funargissement descendant:

 function () {
    var a = 42;
    var f = function () { return a + 1; }
    foo(f); // `foo` is a function declared somewhere else.
}
 

Bien que ce ne soit pas:

 function () {
    var a = 42;
    var f = function () { return a + 1; }
    return f;
}
 

28voto

Gareth Rees Points 31350

Pour mieux comprendre d'où le terme vient de, vous avez besoin de savoir un peu d'histoire.

La raison pour laquelle un vieux Lisp hacker peut distinguer à la baisse funargs de funargs en général, c'est que la baisse funargs sont faciles à mettre en œuvre dans un cadre traditionnel de Lisp qui manque lexical variables, alors que le cas général est dur.

Traditionnellement, une variable locale a été mise en œuvre dans un interpréteur Lisp par l'ajout d'un liant (le symbole nom de la variable, associé à leur valeur) à l' environnement. Un tel environnement a été simple à mettre en œuvre à l'aide d'une association de liste. Chaque fonction a son propre environnement, et un pointeur sur l'environnement de la fonction parente. Une variable de référence a été résolu par la recherche dans l'environnement actuel, et si elles n'y figurent pas, alors dans le parent de l'environnement, et donc sur le haut de la pile des environnements jusqu'à ce que l'environnement mondial a été atteint.

Dans une telle mise en œuvre, les variables locales à l' ombre des variables globales avec le même nom. Par exemple, en Emacs Lisp, print-length est une variable globale qui spécifie la longueur maximale de la liste à imprimer avant de les abréger. Par la liaison de cette variable autour de l'appel à une fonction, vous pouvez modifier le comportement des instructions d'impression, à l'intérieur de cette fonction:

(defun foo () (print '(1 2 3 4 5 6))) ; de sortie dépend de la valeur de l'imprimé-longueur

(foo) ; l'utilisation globale de la valeur de l'imprimé-longueur
 ==> (1 2 3 4 5 6)

(let ((impression de longueur 3)) (foo)) ; lier impression de longueur localement autour de l'appel à toto.
 ==> (1 2 3 ...)

Vous pouvez voir que dans une telle mise en œuvre, la baisse funargs sont vraiment facile à mettre en œuvre, car les variables qui sont dans l'environnement de la fonction au moment de sa création sera toujours dans l'environnement de la fonction lorsqu'elle est évaluée.

Les Variables qui agissent ainsi sont appelés spéciales ou de dynamique des variables, et vous pouvez les créer dans le Common Lisp à l'aide de l' special déclaration.

13voto

Rainer Joswig Points 62532

En Common Lisp:

(let ((a 3))
  (mapcar (lambda (b) (+ a b))
          (list 1 2 3 4)))

->  (4 5 6 7)

Dans la forme ci-dessus, la fonction lambda est passé à la BAISSE. Lorsqu'elle est appelée par la fonction d'ordre supérieur MAPCAR (qui est une fonction et une liste de valeurs en tant qu'arguments, et applique ensuite la fonction à chaque élément de la liste et retourne une liste des résultats), la fonction lambda fait toujours référence à la variable 'a' partir de l'expression. Mais il arrive tout à l'intérieur de l'PERMETTEZ l'expression.

Comparer ci-dessus avec cette version:

(mapcar (let ((a 3))
          (lambda (b) (+ a b)))
        (list 1 2 3 4))

Ici, la fonction lambda est retourné à partir de la LAISSE. Vers le haut un peu. Elle obtient ensuite transmis à la MAPCAR. Lorsque MAPCAR appelle la fonction lambda, de ses environs, LAISSEZ-n'est plus de l'exécution en fonction des besoins de référence de la variable 'a' à partir de la LAISSE.

12voto

Ólafur Waage Points 40104

Il y a un joli descriptif de l'article sur le Wiki appelée Funarg problème

"Une baisse funarg peut également se référer à une fonction de l'état lorsque cette fonction n'est pas réellement en cours d'exécution. Cependant, parce que, par définition, l'existence de haut en bas funarg est contenue dans l'exécution de la fonction il crée, l'activation de l'enregistrement pour les la fonction peut généralement être stockée dans la pile."

Prograide.com

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.

Powered by:

X