web-dev-qa-db-fra.com

Expression lambda Java 8 et valeurs de première classe

Les fermetures Java 8 sont-elles vraiment des valeurs de premier ordre ou s'agit-il uniquement d'un sucre syntaxique?

30
xdevel2000

Je dirais que les fermetures Java 8 ("Lambdas") ne sont ni un simple sucre syntaxique ni des valeurs de première classe.

J'ai abordé la question du sucre syntaxique dans un answer à une autre question StackExchange.

Quant à savoir si les lambdas sont "de première classe", cela dépend vraiment de votre définition, mais je vais expliquer que les lambdas ne sont pas vraiment de première classe.

Dans un certain sens, un lambda veut être une fonction, mais Java 8 n’ajoute pas de types de fonctions. Au lieu de cela, une expression lambda est convertie en une instance d'une interface fonctionnelle. Cela a permis d’ajouter lambdas à Java 8 avec seulement des modifications mineures du système de types de Java. Après la conversion, le résultat est une référence comme tout autre type de référence. En fait, utiliser un Lambda - par exemple, dans une méthode à laquelle une expression lambda a été passée en tant que paramètre - ne peut pas être distingué d'appeler une méthode via une interface. Une méthode qui reçoit un paramètre d'un type d'interface fonctionnelle ne peut pas dire si une expression lambda ou une instance d'une classe lui a été transmise pour implémenter cette interface fonctionnelle.

Pour plus d'informations sur le point de savoir si les lambdas sont des objets, consultez la Lambda FAQ Answer à cette question.

Étant donné que les lambdas sont convertis en objets, ils héritent (littéralement) de toutes les caractéristiques des objets. En particulier, les objets:

  • avoir diverses méthodes comme equals, getClass, hashCode, notify, toString et wait
  • avoir un code de hachage d'identité
  • peut être verrouillé par un bloc synchronized
  • peut être comparé en utilisant les opérateurs == et != et instanceof

et ainsi de suite. En fait, tous ces éléments sont non pertinents par rapport à l'utilisation prévue de lambdas. Leur comportement est essentiellement indéfini. Vous pouvez écrire un programme qui utilise n'importe lequel de ces éléments et vous obtiendrez des résultats, mais ceux-ci peuvent différer d'une version à une autre (ou même s'exécuter pour s'exécuter!).

En reformulant ceci de manière plus concise, en Java, les objets ont identité, mais les valeurs (en particulier les valeurs de fonction, si elles devaient exister) ne devraient pas avoir de notion d'identité. Java 8 n'a pas de type de fonction. Au lieu de cela, les expressions lambda sont converties en objets, elles ont donc beaucoup de bagages qui sont sans rapport avec les fonctions, en particulier l'identité. Cela ne me semble pas être "de première classe".

Mise à jour 2013-10-24

Je réfléchis davantage à ce sujet depuis que j'ai posté ma réponse il y a plusieurs mois. D'un point de vue technique, tout ce que j'ai écrit ci-dessus est correct. La conclusion s’explique probablement plus précisément par le fait que Java 8 lambdas n’est pas une valeur de {pure (par opposition à de première classe) _), car elle entraîne beaucoup de bagages. Cependant, ce n'est pas parce qu'ils sont impurs qu'ils ne sont pas de première classe. Considérons la définition Wikipedia de fonction de première classe. En bref, les critères énumérés ici pour considérer les fonctions de première classe sont les capacités à:

  • passer des fonctions comme arguments à d'autres fonctions
  • renvoyer des fonctions d'autres fonctions
  • assigner des fonctions aux variables
  • fonctions de stockage dans des structures de données
  • avoir des fonctions être anonyme

Les lambdas Java 8 répondent à all de ces critères. Donc, cela les fait paraître de première classe.

L'article mentionne également que les noms de fonction n'ayant pas de statut spécial, le nom d'une fonction est simplement une variable dont le type est un type de fonction. Les lambdas Java 8 ne répondent pas à ce dernier critère. Java 8 n'a pas de type de fonction; il a des interfaces fonctionnelles. Ceux-ci sont utilisés efficacement comme des types de fonction, mais ils ne sont pas du tout. Si vous avez une référence dont le type est une interface fonctionnelle, vous ne savez pas s'il s'agit d'une lambda, d'une instance d'une classe interne anonyme ou d'une instance d'une classe concrète qui implémente cette interface.

En résumé, les lambdas Java 8 sont davantage des fonctions de première classe que je ne l’avais imaginé au départ. Ce ne sont tout simplement pas des fonctions {pures} _ de première classe.

56
Stuart Marks

Yes , ce sont des valeurs de première classe (ou le seront, une fois Java 8 publié ...)

En ce sens que vous pouvez les transmettre sous forme d'arguments, les composer pour créer des fonctions d'ordre supérieur, les stocker dans des structures de données, etc. Vous pourrez les utiliser pour un large éventail de techniques de programmation fonctionnelles.

Voir aussi pour un peu plus de définition de ce que "première classe" signifie dans ce contexte:

6
mikera

À mon avis, il s'agit d'un sucre syntaxique, mais en plus de l'inférence de type, d'un nouveau paquetage Java.util.functions et de la sémantique des classes internes, il apparaît comme une valeur de première classe.

2
kan

Une fermeture réelle avec une liaison variable au contexte extérieur a des frais généraux. Je considérerais que la mise en oeuvre de Java 8 est optimale, suffisamment pure.

Ce n'est pas simplement du sucre syntaxique, du moins.

Et je ne saurais pas d'une mise en œuvre plus optimale.

1
Joop Eggen

Pour moi, Lambdas dans Java 8 n’est que syntax sugar car vous ne pouvez pas l’utiliser comme citoyen de première classe ( http://en.wikipedia.org/wiki/First-class_function ), chaque fonction doit être encapsulé dans un objet, il impose de nombreuses limitations lorsqu’on le compare à un langage avec une fonction pure de première classe comme SCALA. Les fermetures Java 8 ne peuvent capturer que des variables non locales immuables ("effectivement définitives").

Voici une meilleure explication pourquoi syntax-sugar Java Lambdas and Closures

0
Lemberg