Je me demande quelles sont les différences de mise en œuvre technique entre C # et Scala et comment les deux solutions se comparent aux idées et préoccupations de mise en œuvre exprimées dans l'e-mail Peek Past lambda de Brian Goetz, envoyé à la liste de diffusion du projet Lambda (JSR 335) ?
De l'email:
Nous avons exploré la voie «peut-être que les lambdas ne devraient être que des instances de classe interne, ce serait vraiment simple», mais nous sommes finalement arrivés à la position «les fonctions sont une meilleure direction pour l'avenir du langage».
et plus loin:
La vision lambdas-are-objets du monde est en conflit avec ce futur possible. La vision lambdas-are-functions du monde ne le fait pas, et la préservation de cette flexibilité est l'un des points en faveur de ne pas surcharger les lambdas avec même l'apparence d'objectivité.
Conclusion:
Lambdas-are-functions ouvre des portes. Lambdas-are-objects les ferme.
Nous préférons voir ces portes ouvertes.
Et certains commentaires d'une personne sur le fil Reddit disent:
En fait, j'ai envoyé un courriel à Neal Gafter à ce sujet et à ma compréhension limitée de son explication, C # et la conception Java actuelle sont assez similaires en ce sens que les délégués sont en fait des objets et non des types de fonctions. Il semble qu'il pense que Java devrait apprendre des inconvénients des lambdas de C # et les éviter (un peu comme C # a appris des inconvénients de Java et les a évités au début).
Pourquoi l'approche "Lambdas-are-functions" ouvre-t-elle davantage de possibilités à l'avenir que "Lambdas-are-objects"? Quelqu'un peut-il expliquer quelles différences existent et comment elles influenceraient la façon dont le code serait écrit?
Voyant que les choses dans Scala "fonctionnent juste", je continue de penser que je manque quelque chose au sujet des approches adoptées / proposées en C # / Java (8), probablement est-ce lié à des préoccupations concernant la rétrocompatibilité?
Réponses:
Je pense que la discussion concernant les objets par rapport aux fonctions est un hareng rouge. Si la question est: "Un lambda est-il une fonction ou un objet?" la réponse devrait être oui .
C'est le point des fonctions de première classe: elles ne sont pas traitées différemment de tout autre type. Java parvient déjà à ignorer la plupart des différences entre les types Object et primitifs (et Scala fait encore mieux), donc si un lambda est une sous-classe d'Object ou est un nouveau type primitif ou autre chose n'est pas vraiment important pour le langage. Ce qui est important, c'est que vous pouvez mettre vos lambdas dans des collections, les transmettre pour être appelés, les appeler et faire tout ce que vous voudrez faire avec un objet ou une méthode.
Scala accomplit cela en utilisant un objet wrapper qui a une méthode appelée
apply
qui peut être invoquée avec just()
, ce qui la fait ressembler à un appel de méthode. Cela fonctionne à merveille; la plupart du temps, vous n'avez même pas besoin de vous soucier de savoir si vous avez une méthode ou si vous appelez l'application d'un objet fonction.la source
D'après ce que je comprends, il s'agit davantage de la façon dont les lambdas sont considérés au niveau de la langue principale. Comme le dit l'e-mail,
Je pense que cela résume très bien votre question. Si vous déclarez que "les lambdas sont des objets", alors ils ne sont qu'un objet d'une classe particulière et vous êtes coincé avec cela. D'un autre côté, si vous déclarez que "les lambdas sont des fonctions", alors sémantiquement vous avez un terrain de jeu beaucoup plus riche. Java 1.7 peut les compiler en objets, ils sont donc pratiquement identiques à ce stade.
Mais Java 1.8, ou 1.9, pourrait apporter des changements au langage (tels que des types structurels réifiés) que permettre aux fonctions d'être utilisées de manière beaucoup plus flexible. Si "les lambdas étaient des objets", ces changements ne seraient pas rétrocompatibles et il faudrait introduire un nouveau concept au total, afin de ne pas casser le code existant des gens. Mais si
javac
je convertissais simplement des lambdas en objets en coulisses, le nouveaujavac
peut les convertir en tout ce qu'il veut, tant que la sémantique tient toujours.la source
foreach
,map
,filter
aux collections.Surtout, il ne veut tout simplement pas s'engager trop tôt dans quelque chose. Je ne vois aucune raison au-delà de l'effacement qu'il a présenté, mais c'est vraiment une raison très forte.
Considérez ces méthodes dans Scala
Regex
:Ce serait plus simple s'ils étaient simplement ceci:
Malheureusement, ce n'est pas possible, car ces deux fonctions sont identiques à l'effacement. Mais, très bien, ces fonctions font des choses quelque peu différentes, donc un nom différent pourrait être assez juste.
Cependant, a
Match
est quelque chose de très utile, mais la plupart du temps vous voulez soit la correspondance,String
soit la liste des sous-groupes. Nous aimerions avoir ceci:Pas possible, à cause de l'effacement. J'ai choisi cet exemple particulier parce que j'y étais directement impliqué, mais j'ai vu au moins une demi-douzaine de questions sur Stack Overflow, où les gens demandent pourquoi une surcharge est illégale, causée par ce problème exact.
Et puis, considérez que la mise en correspondance des motifs de Scala et celle de Java
instanceof
sont effectivement inutiles à cause de l'effacement.Je pense qu'il est juste de retarder les types de fonctions jusqu'à ce que ce problème soit réglé. Après tout, il existe de nombreux langages sur la JVM, et ce n'est pas comme si Java était un langage en évolution rapide.
la source