38 votes

Qu'est-ce que "Levage Lambda"?

Je viens de rencontrer ceci en passant par la source du compilateur Erlang.

Je ne comprends pas vraiment. (allez comprendre;)), considérant que je viens de me rendre compte qu'il y a une telle chose il y a 5 minutes).

Pardonnez-moi de demander d'abord sans essayer d'abord de comprendre les raisons de son existence.

Il existe un article sur wikipedia à ce sujet, mais il est assez cryptique.

49voto

Doug Currie Points 26016

Lambda de levage est utilisé pour transformer une fermeture en fonction pure. En passant des arguments supplémentaires à la fonction, vous réduisez le nombre de ses variables libres. Comme vous le "lift" la lambda en plus élevés et plus étendues, vous ajouter des arguments pour accueillir les variables locales déclarées dans ce champ d'application (ce qui serait variables libres contraire). Une fois que le lambda n'a pas de variables libres c'est un pur "haut niveau" de la fonction.

Bien sûr, vous pouvez faire cela seulement si vous savez tous les lambda sites d'appel; en d'autres termes, que si le lambda ne s'échappe pas.

L'avantage dans un compilateur optimiseur est que la fermeture (fonction environnements) peuvent être éliminés. Cela peut permettre de passer les arguments dans les registres plutôt que de la pile (ou un segment) attribution comme des variables libres.

39voto

Tom Lokhorst Points 7733

Lambda-lifting est une technique de lift lambdas à un niveau plus élevé (surtout pour le niveau supérieur).

Doug Currie, qui explique pourquoi vous voulez le faire.

Voici un exemple de code (en JavaScript) de la façon dont vous pouvez le faire manuellement:

function addFive(nr)
{
  var x = 5;
  function addX(y)
  {
    return x + y;
  }

  return addX(nr);
}

Maintenant, si vous ne voulez pas de cette addX fonction à l'intérieur de la définition de l' addFive vous pourriez d " ascenseur `il vers le haut niveau comme suit:

function addX(y)
{
  return x + y;
}

function addFive(nr)
{
  var x = 5;

  return addX(nr);
}

Toutefois, cela ne fonctionne pas, car l' x variable n'est plus disponible dans le contexte de l' addXfonction. Le moyen de résoudre ce problème est d'ajouter un paramètre formel de la fonction:

function addX(y, x)
{
  return x + y;
}

function addFive(nr)
{
  var x = 5;

  return addX(nr, x);
}


Ajout: Voici un exemple artificiel d'un lambda "s'échappe". Où vous ne serez pas en mesure de faire le lambda-lifting aussi facilement que je l'ai décrit.

function getAddFiveFunc()
{
  var x = 5;
  function addX(y)
  {
    return x + y;
  }

  return addX;
}

Maintenant, si quelqu'un appelle l' getAddFiveFunc fonction, ils auront une fonction de retour. Cette fonction peut être utilisée dans toutes sortes d'endroits, Maintenant, si vous ne voulez soulever l' addX fonction, vous devez mettre à jour tous ceux callsites.

1voto

JaredPar Points 333733

Avertissement: Ma réponse décrit en fait capturé variables qui est différent de celui lambda de levage. Mal lu la question (besoin de sommeil). Mais j'ai passé un peu de temps à écrire ce donc je suis réticent à le supprimer. À gauche comme un WIKI de la communauté.

Lambda de levage, souvent désigné comme les fermetures, est une façon de façon transparente permettant l'accès de la portée des variables à partir de l'intérieur d'un ensemble d'expressions lambda.

Il est difficile d'entrer dans les détails concrets de fermetures sans choisir une langue en particulier. L'un des effets secondaires de lambda de levage, en toutes langues, c'est qu'il a tendance à prolonger la durée de vie d'une variable à partir d'un local à durée de vie courte portée, beaucoup plus vécu portée. Habituellement, cela se produit sous la forme d'un transfert d'une variable de la pile sur le tas dans le compilateur. C'est une langue très spécifique de l'action et, par conséquent, produit de très différentes implémentations basées sur la langue.

Je vais me concentrer sur C# car c'est probablement la langue la plus commune pour les lecteurs de débordement de la pile. Permet de commencer avec le code suivant.

public Func<int> GetAFunction() {
  var x = 42;
  Func<int> lambda1 = () => x;
  Func<int> lambda2 = () => 42;
  ...
  return lambda1;
}

Dans cet exemple, nous avons créé 2 les expressions lambda. Dans les deux cas, il est attribué à un représentant de l'instance de type Func. Tous les délégués .Net exiger qu'une fonction réelle de sauvegarde quelque part. Sous le capot, toutes les expressions lambda/ fonctions anonymes en C# sont traduites dans une définition de la méthode.

La génération d'une fonction pour lambda2 est assez simple. C'est un cas isolé fonction qui retourne une valeur constante.

public static int RealLambda2() { 
  return 42;
}

Générer lambda1 est un peu plus difficile. Une définition littérale serait la suivante

public static int RealLambda1() {
  return x;
}

De toute évidence, cela ne compile pas parce que x n'est pas accessible. Afin de rendre ce travail, le compilateur C# doit soulever la variable x dans une clôture. Il peut alors retourner un pointeur vers une fonction à l'intérieur de la fermeture à satisfaire le délégué de l'expression

class Closure1 {
  int x;
  public int RealLambda1() {
    return x;
  }
}

C'est un exemple assez simple, mais devrait, espérons-le détail de l'art de levage. Le diable est malheureusement dans les détails et devient beaucoup plus complexe avec le scénario.

0voto

Jon W Points 7032

La levée lambda élimine essentiellement les variables et les met dans des fonctions pures, simplifiant l'exécution.

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