33 votes

Fermetures en Scala vs Fermetures en Java

Il y a quelques temps Oracle a décidé que l'ajout de Fermetures de Java 8 serait une bonne idée. Je me demande comment concevoir les problèmes sont résolus, il y en comparaison à la Scala, qui avait fermetures depuis le premier jour.

Citant les Problèmes de javac.info:

  1. Peut-Méthode Gère être utilisé pour des Types de Fonction? Il n'est pas évident pour vous de faire ce travail. Un problème est que la Méthode de Poignées de réification des paramètres de type, mais d'une manière qui interfère avec la fonction de sous-typage.

  2. Peut-on se débarrasser de la déclaration explicite de "lance" paramètres de type? L'idée serait d'utiliser disjuntive l'inférence de type à chaque fois que l'a déclaré lié est un activée type d'exception. Ce n'est pas strictement compatible, mais il est peu probable que de briser véritable code existant. On ne peut probablement pas se débarrasser de la "jette" dans le type de l'argument, cependant, en raison d'ambiguïté syntaxique.

  3. Interdire @Partagé sur style ancien indice de boucle variables

  4. Gérer les interfaces Comparateur qui définissent plus d'une méthode, tous, sauf un, qui sera mis en œuvre par une méthode héritée de l'Objet. La définition de "interface avec une seule méthode" doit compter uniquement les méthodes qui ne seraient pas mises en œuvre par une méthode dans un Objet et doit compter plusieurs méthodes comme l'un, si la mise en œuvre de l'un d'eux serait de mettre en œuvre toutes. Principalement, ce qui nécessite une plus grande précision de ce que cela signifie pour une interface d'avoir une seule méthode abstraite.

  5. Spécifier le mappage à partir de la fonction de types d'interfaces: les noms, les paramètres, etc. Nous devrions spécifier le mappage à partir de la fonction de types générés par le système et les interfaces avec précision.

  6. L'inférence de Type. Les règles d'inférence de type doivent être augmentée pour accueillir l'inférence de type d'exception paramètres. De même, le sous-type de relations utilisées par la fermeture de conversion devrait être traduit ainsi.

  7. Élidés exception des paramètres de type pour aider à rénover exception de la transparence. Peut-être élidés exception des paramètres de type moyenne du lié. Cela permet de rénovation existant interfaces génériques qui n'ont pas de paramètre de type de l'exception, comme java.util.de façon concomitante.Rachetables, par l'ajout d'un nouveau générique paramètre d'exception.

  8. Comment font partie de la classe des littéraux pour des types de fonction formé? Est-il #void().de classe ? Si oui, comment ça fonctionne si les types d'objets sont effacées? Est-ce #?(?).de classe ?

  9. Le système de chargeur de classe devrait générer dynamiquement le type de fonction d'interface. Les interfaces correspondant à des types de fonction doivent être générés à la demande, par la classe de bootstrap loader, de sorte qu'ils peuvent être partagées entre tous les utilisateurs du code. Pour le prototype, nous avons javac générer ces interfaces afin de prototype généré le code peut s'exécuter sur stock (JDK5-6) les machines virtuelles.

  10. Doit l'évaluation d'une expression lambda produire une nouvelle objet à chaque fois? J'espère que non. Si un lambda capte pas de variables à partir d'un cadre englobant, par exemple, il peut être allouée de manière statique. De même, dans d'autres situations, lambda pourrait être déplacé hors d'une boucle interne si elle ne rend pas compte de toutes les variables déclarées à l'intérieur de la boucle. Il serait donc pour le mieux si les spécifications ne promet rien quant à la référence à l'identité du résultat d'une expression lambda, de sorte que ces optimisations peuvent être fait par le compilateur.

Comme je le comprends 2., 6. et 7. ne sont pas un problème en Scala, parce que Scala n'utilise pas Vérifié les Exceptions comme une sorte de "Shadow" type de système" comme Java.

Quid du reste?

29voto

James Iry Points 14192

1) la Méthode des Poignées d'être utilisés pour des Types de Fonction?

Scala cibles JDK 5 et 6 qui n'ont pas de méthode de poignées, de sorte qu'il n'a pas essayé de résoudre le problème encore.

2) Peut-on se débarrasser de la déclaration explicite de "lance" paramètres de type?

Scala n'a pas vérifié les exceptions.

3) Refuser @Partagé sur style ancien indice de boucle variables.

Scala n'a pas de boucle d'index des variables. Toujours, la même idée peut être exprimée avec une certaine sorte de boucle while . Scala, à la sémantique sont assez standard ici. Les symboles de liaisons sont capturés et si le symbole de arrive à la carte pour une mutable cellule de référence, puis sur votre propre tête soit-il.

4) Gérer les interfaces Comparateur qui définissent plus d'une méthode tout, mais qui viennent de l'Objet

Scala, les utilisateurs ont tendance à utiliser des fonctions (ou des fonctions implicites) de contraindre des fonctions du type de droit à une interface. par exemple

[implicit] def toComparator[A](f : (A, A) => Int) = new Comparator[A] { 
    def compare(x : A, y : A) = f(x, y) 
}

5) Préciser la cartographie de la fonction de types d'interfaces:

Scala, à la bibliothèque standard comprend FuncitonN traits pour 0 <= N <= 22 et la spécification dit que la fonction littéraux de créer des instances de ces traits

6) l'inférence de Type. Les règles d'inférence de type doivent être augmentée pour accueillir l'inférence de type d'exception paramètres.

Depuis Scala n'a pas vérifié les exceptions qu'il peut punt sur cette question

7) Élidés exception des paramètres de type pour aider à rénover exception de la transparence.

Même affaire, aucune checked exceptions.

8) Comment font partie de la classe des littéraux pour des types de fonction formé? Est-il #void().de classe ? Si oui, comment ça fonctionne si les types d'objets sont effacées? Est-ce #?(?).de classe ?

classOf[A => B] //or, equivalently, 
classOf[Function1[A,B]]

Type d'effacement est le type d'effacement. Ci-dessus les littéraux de produire de la scala.lang.Fonction1 quel que soit le choix de A et B. Si vous préférez, vous pouvez écrire

classOf[ _ => _ ] // or
classOf[Function1[ _,_ ]]

9) Le système de chargeur de classe devrait générer dynamiquement le type de fonction d'interface.

Scala limite arbitrairement le nombre d'arguments pour être au plus 22 de sorte qu'il n'a pas à générer le Fonctionn classes dynamiquement.

10) l'évaluation d'une expression lambda produire une nouvelle objet à chaque fois?

La Scala spécification ne veut pas dire qu'il doit. Mais comme de 2.8.1 le le compilateur n'a pas optimise le cas où un lambda ne capte rien de son environnement. Je n'ai pas testé avec 2.9.0 encore.

12voto

Daniel C. Sobral Points 159554

Je vais aborder uniquement le numéro 4 ici.

L'une des choses qui distingue Java "fermetures" de fermetures trouvé dans d'autres langues, c'est qu'ils peuvent être utilisés en lieu et place de l'interface qui n'a pas de décrire une fonction, par exemple, Runnable. C'est ce que l'on entend par SAM, une Seule Méthode Abstraite.

Java n'est-ce parce que ces interfaces abondent dans la bibliothèque Java, et ils sont nombreux dans la bibliothèque Java parce que Java a été créé sans la fonction ou de types de fermetures. En leur absence, chaque code d'inversion de contrôle a dû recourir à l'aide d'un SAM interface.

Par exemple, Arrays.sort prend un Comparator objet qui va effectuer la comparaison entre les membres du tableau à trier. En revanche, la Scala pouvez trier List[A] par la réception d'une fonction (A, A) => Int, ce qui est facilement transmis par le biais d'une fermeture. Voir la note 1 à la fin, cependant.

Donc, parce que la Scala, à la bibliothèque a été créée pour une langue avec des types de fonction et de fermetures, il n'y a pas besoin de l'appui d'une telle chose que SAM fermetures en Scala.

Bien sûr, il y a une question de la Scala/Java interopérabilité -- tandis que la Scala, à la bibliothèque ne pourrait pas besoin de quelque chose comme SAM, Java bibliothèque. Il y a deux façons qui peuvent être résolus. D'abord, parce que Scala prend en charge les fermetures et les types de fonction, il est très facile de créer des méthodes d'assistance. Par exemple:

def runnable(f: () => Unit) = new Runnable {
    def run() = f()
}

runnable { () => println("Hello") } // creates a Runnable

En fait, cet exemple en particulier, peut être encore plus court par l'utilisation de Scala par les paramètres de nom, mais c'est à côté de la question. De toute façon, c'est quelque chose qui, sans doute, Java aurait fait à la place de ce qu'il va faire. Compte tenu de la prévalence de SAM interfaces, il n'est pas surprenant.

L'autre façon Scala poignées c'est par le biais de conversions implicites. Simplement en ajoutant implicit de la runnable méthode ci-dessus, on crée une méthode qui obtient automatiquement (note 2) s'applique chaque fois qu'un Runnable est nécessaire, mais une fonction () => Unit est prévue.

Implicites sont uniques, cependant, et encore controversée, dans une certaine mesure.

Note 1: en Fait, cet exemple en particulier, a été de choisir avec une certaine malice... Comparator a deux méthodes abstraites au lieu d'un, ce qui est tout le problème avec elle. Puisque l'un de ses méthodes peuvent être mises en œuvre en termes de l'autre, je pense qu'ils vont juste "soustraire" défenseur des méthodes de l'abrégé de la liste.

Et, sur la Scala de côté, même si il y a une sorte de méthode qui utilise (A, A) => Boolean, pas (A, A) => Int, le standard de la méthode de tri des appels pour un Ordering de l'objet, qui est assez similaire à Java Comparator! En Scala cas, cependant, Ordering joue le rôle d'un type de classe.

Note 2: Implicites sont appliquées automatiquement, une fois qu'ils ont été importés dans la portée.

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