IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Quel avenir pour le langage Scala depuis l'arrivée de Java 8,
Venez partager votre expérience

Le , par Mickael Baron

99PARTAGES

4  0 
L'équipe Java vous propose un débat sur la pertinence d'utiliser le langage fonctionnel Scala depuis que la nouvelle version de Java supporte désormais la programmation fonctionnelle. En effet si l'on regarde le forum dédié à Scala sur Developpez.com, on remarque que ce dernier ne contient que très peu de discussions. De même, avec la concurrence féroce du langage JavaScript et de Node.JS pour le développement web, les langages basés sur la JVM y compris Scala, sont en perte de vitesse.

Nous souhaiterions que vous profitiez de cette discussion pour donner votre point de vue quant à votre utilisation de Scala.

Utilisez-vous seul Scala ou conjointement avec le langage Java permettant selon les circonstances de tirer réellement parti des avantages respectifs des deux langages.

Merci d'avance

Mickael pour l'équipe Java

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de sjrd
Expert éminent sénior https://www.developpez.com
Le 05/01/2016 à 0:25
Je suis assez d'accord avec l'opinion d'Adraor. Avoir des lambdas n'est pas la clef de la programmation fonctionnelle. C'est bien sûr un des points nécessaires d'un langage visant à être fonctionnel, mais en aucun cas il n'est suffisant.

Au-delà de tout, c'est l'immuabilité qui conditionne le paradigme fonctionnel. Bien qu'il soit possible de programmer de manière immuable en Java, il faut littéralement se battre contre le langage pour y parvenir. Des final à tous les coins de rue, éviter les collections natives de java.util, à moins de tout wrapper avec des Collections.unmodifiableXYZ(). Ce n'est tout simplement pas une vie.

Scala, comme les autres langages fonctionnels, encourage au contraire l'immuabilité. Et c'est ça qui fait toute la différence !

Quant aux autres fonctionnalités du langage telles que le pattern matching ou les tail recursive calls, ce sont bien sûr des plus, mais ils sont loin derrière l'immuabilité comme caractéristiques d'un paradigme fonctionnel. Par exemple, les LISP n'ont pas de pattern matching dans le langage, et sont pourtant unanimement reconnus comme fonctionnels. Inversement, C a depuis longtemps des tail recursive calls, mais je ne pense pas que quiconque avancerait que C est un langage fonctionnel.

Pour la même raison, JavaScript ne deviendra pas fonctionnel de si tôt. Et pourtant JS avait des fonctions anonymes/lambdas depuis le début.
4  0 
Avatar de Adraor
Membre à l'essai https://www.developpez.com
Le 04/01/2016 à 22:18
Bonjour à tous,

Je réagis à cette discussion pour donner mon avis sur la question, et je vais vous expliquer pourquoi, selon moi, la question posée n'a pas de sens.
Tout d'abord un fait :
Java (peu importe la version) ne supporte pas la programmation fonctionnelle... le fait de pouvoir faire des lambdas n'est pas tout, (le fonctionnel est un paradigme à part entière! )
Je n'ai aucunement la prétention de donner un cours mais même si je n'ai pas une expérience très significative en programmation fonctionnelle,
je sais que les 3 principes fondamentaux sont:

-L'immutabilité: on ne réaffecte pas de valeur à une 'variable' qui est ducoup une constante
Les langages fonctionnels encouragent la déclaration d'objets et collections immuables pour un code plus safe.

-Le pattern matching : à ne surtout pas confondre avec les switch cases, le pattern matching permet de conditionner sur la structure des objets, collections, leurs types etc...

-La récursivité : ça existe en Java mais c'est pas très conseillé a cause de StackOverFlow (tout le monde la connais celle là) ,
En Scala (entre autre) on a la notion de tail-récursivité c'est une optimisation qui va permettre de pouvoir TOUT coder de maniérè récursive sans dépasser les limites du Stack.

Surtout corrigez moi si je me trompe mais je pense que JAVA (8) n'en implémente aucun...

-L'immutabilité n'est absolument pas au cœur des préoccupations des développeurs Java, certains mécanisme du langage encouragent même l'utilisation des effets de bords.
-Le pattern matching : nop
-Et pas de tail récursivité en Java

Mis à part ces principes généraux, d'autres bien plus subtils font toute la richesse du paradigme fonctionnel, je pense en premiers aux types implicites, au monades, aux fonctions d'ordre supérieur... et bien d'autre.
Sans même parler des collections en Scala qui proposent énormément de fonctionnalités.
Il n'y a cependant qu'un seul moyen de vraiment comprendre l'interêt de faire du Scala : faire du Scala, vous comprendrez par la même occasion l’intérêt de ne plus faire de Java.
Bref Java n'est absolument pas un langage fonctionnel, et il ne le sera probablement jamais ; Scala , en revanche est un langage multi-paradigme super sympa qui souffre malheureusement des défauts de la JVM.
4  2 
Avatar de Traroth2
Membre émérite https://www.developpez.com
Le 05/01/2016 à 10:02
Citation Envoyé par Adraor Voir le message
Scala , en revanche est un langage multi-paradigme super sympa qui souffre malheureusement des défauts de la JVM.
J'avais poucé ton commentaire, jusqu'à cette phrase. De quels défauts de la JVM parle-tu ?

Le rôle de la JVM n'est pas de favoriser la programmation fonctionnelle. Si on devait la faire évoluer, ça serait vers toujours plus d'agnosticisme par rapport aux langages de programmation.
2  0 
Avatar de gorgonite
Rédacteur/Modérateur https://www.developpez.com
Le 05/01/2016 à 21:54
Citation Envoyé par Adraor Voir le message

Citation Envoyé par Tharoth2
De quels défauts de la JVM parle-tu ?

Le rôle de la JVM n'est pas de favoriser la programmation fonctionnelle. Si on devait la faire évoluer, ça serait vers toujours plus d'agnosticisme par rapport aux langages de programmation.
Absolument, je suis tout a fait conscient que la JVM ne peut tout optimiser, et ce n'est absolument pas ce que je lui reproche...
Quand je parle d'inconvenants, j'évoque en premier l’effacement de type, cela ne facilite pas la vie des programmeurs utilisant de manière un peu
poussée les types génériques et provoque des incohérences, lors des comparaisons de type...

On peut parler d'un défaut majeur : l'impossibilité d'avoir la tail-call optimization (reference), ce qui oblige à passer entre autres par l'annotation @tailrec ou à avoir des récursions extrêmement simples (le compilateur s'est peut-être amélioré sur ce point, je n'ai pas testé depuis un moment)
2  0 
Avatar de sjrd
Expert éminent sénior https://www.developpez.com
Le 06/01/2016 à 17:16
Il ne s'agit pas de "récursion extrêmement simple". Il s'agit de fonctions tail-recursive (par opposition aux tail calls en général). L'annotation @tailrec n'est pas nécessaire; elle est une aide au programmeur, qui lui permet d'être certain qu'une fonction est effectivement tail-recursive. Le compilateur optimisera les fonctions tail-recursive qu'elle soient annotées avec @tailrec ou pas.

D'après mon expérience (et je code en Scala tous les jours depuis 3 ans), les tail calls généralisés sont extrêmement rarement nécessaires/utiles. Et même les tail-recursive calls, je n'en utilise pas tant que ça (on s'en sort généralement avec les méthodes des collections). Dans les rares cas où les tail calls sont vraiment nécessaires, on peut faire du trampolining.

Quant à l'effacement de type (type erasure), c'est un faux reproche. Il y a des inconvénients, mais aussi des avantages. S'il n'y avait pas de type erasure, les développeurs se rendraient compte de tous les cas où la type erasure est bénéfique, et reprocheraient au langage de ne pas l'avoir. Pour les inconvénients, on peut généralement les solutionner avec des ClassTag ou, au besoin, des TypeTag.
2  0 
Avatar de JavaBean
Membre habitué https://www.developpez.com
Le 05/01/2016 à 10:05
Merci pour ces précisions. Vous qui semblez maîtriser le sujet, auriez-vous de bons tutoriels/cours/livres à conseiller?
0  0 
Avatar de gorgonite
Rédacteur/Modérateur https://www.developpez.com
Le 06/01/2016 à 18:55
Citation Envoyé par sjrd Voir le message
Il ne s'agit pas de "récursion extrêmement simple". Il s'agit de fonctions tail-recursive (par opposition aux tail calls en général). L'annotation @tailrec n'est pas nécessaire; elle est une aide au programmeur, qui lui permet d'être certain qu'une fonction est effectivement tail-recursive. Le compilateur optimisera les fonctions tail-recursive qu'elle soient annotées avec @tailrec ou pas.

D'après mon expérience (et je code en Scala tous les jours depuis 3 ans), les tail calls généralisés sont extrêmement rarement nécessaires/utiles. Et même les tail-recursive calls, je n'en utilise pas tant que ça (on s'en sort généralement avec les méthodes des collections). Dans les rares cas où les tail calls sont vraiment nécessaires, on peut faire du trampolining.

Ben justement c'est simple comme récursion... d'un point de vue théorique ou comparé aux exemples naïfs qu'on montre habituellement aux étudiants débutant en programmation fonctionnelle.
Au passage, j'ai souvenir qu'à une époque (entre 2007 et 2009, de tête), cela optimisait quand même moins que cela

Après je ne dis pas que ce n'est pas suffisant pour la plupart des cas

Citation Envoyé par sjrd Voir le message
Quant à l'effacement de type (type erasure), c'est un faux reproche. Il y a des inconvénients, mais aussi des avantages. S'il n'y avait pas de type erasure, les développeurs se rendraient compte de tous les cas où la type erasure est bénéfique, et reprocheraient au langage de ne pas l'avoir. Pour les inconvénients, on peut généralement les solutionner avec des ClassTag ou, au besoin, des TypeTag.
+1, le but d'une machine virtuelle est d'exécuter rapidement un programme, voire parfois aussi de gérer au mieux la mémoire... pas de faciliter le travail de retroingénierie, l'analyse statique du bytecode & cie

D'ailleurs le même reproche peut être fait à .Net dans une moindre mesure (pas les generics, mais le bytecode est bien simplifié à un moment, sinon on ne s'en sortirait pas... ex : essayez le reverse-engineering de bytecode compilé depuis des sources utilisant des dynamics ; idem avec IL et ILX)
0  0 
Avatar de sjrd
Expert éminent sénior https://www.developpez.com
Le 07/01/2016 à 0:42
Citation Envoyé par gorgonite Voir le message
Ben justement c'est simple comme récursion... d'un point de vue théorique ou comparé aux exemples naïfs qu'on montre habituellement aux étudiants débutant en programmation fonctionnelle.
Huh ? Dans mon souvenir, tous les exemples qu'on voit quand on étudie la programmation fonctionnelle sont tail-recursive, et n'ont pas besoin des tail calls généralisés. À part l'exemple canonique mais artificiel de `isEven` et `isOdd` qui s'appellent récursivement l'une l'autre, mais c'est une mauvaise implémentation de toutes façons.

À quel exemple nécessitant les tail calls généralisés penses-tu ?
0  0 
Avatar de gorgonite
Rédacteur/Modérateur https://www.developpez.com
Le 07/01/2016 à 1:39
Citation Envoyé par sjrd Voir le message
Huh ? Dans mon souvenir, tous les exemples qu'on voit quand on étudie la programmation fonctionnelle sont tail-recursive, et n'ont pas besoin des tail calls généralisés. À part l'exemple canonique mais artificiel de `isEven` et `isOdd` qui s'appellent récursivement l'une l'autre, mais c'est une mauvaise implémentation de toutes façons.

À quel exemple nécessitant les tail calls généralisés penses-tu ?
  • effectivement le classique isEven/isOdd
  • toutes les traductions naïves d'une formule mathématique, qu'on nous apprend juste après à transformer en récursion terminale (fibonacci, etc.) avec des astuces type accumulateurs ; afin de ne jamais attendre le résultat de l'appel récursif pour faire des calculs dans la fonction, mais qu'elle termine soit directement, soit par l'appel récursif
  • on mangeait pas mal de graphes en prépa, et assez rarement tail recursive ; seule l'algorithmie comptait (le hic pour les étudiants qui voulaient faire de gros exemples en TIPE)


Sauf erreur de traduction tail-recursive = récursif terminal ; on apprend souvent aux débutants à reformuler en récursif terminal les formules traduites naïvement depuis l'approche mathématique (dite plus naturelle)... on ne mange presque que cela en sup (cela date un peu, mais quand même ). c'est très scolaire, mais cela a le mérite d'éliminer les stack overflow pour la spé. C'est peut-être spécifique à l'enseignement d'il y a 15 ans en France
0  0 
Avatar de Adraor
Membre à l'essai https://www.developpez.com
Le 07/01/2016 à 10:21
Citation Envoyé par sjrd Voir le message

Quant à l'effacement de type (type erasure), c'est un faux reproche. Il y a des inconvénients, mais aussi des avantages. S'il n'y avait pas de type erasure, les développeurs se rendraient compte de tous les cas où la type erasure est bénéfique, et reprocheraient au langage de ne pas l'avoir. Pour les inconvénients, on peut généralement les solutionner avec des ClassTag ou, au besoin, des TypeTag.
Peut être y à t'il des avantages en effet.
Mais je programme régulièrement en C# (qui n'utilise pas le type erasure), et je n'ai absolument pas été surpris (pas dans le mauvais sens du terme)...
Je pense qu'un développeur utilisateur de la JVM étant donc habitué à utiliser des patterns pour contourner les 'travers' de l’effacement de type (ce que je trouve déjà anormal), sera surpris lors de l'utilisation d'un langage qui ne confond pas une collection de patate et de carottes...
Alors si il y a effectivement des avantages que l'on ne retrouve que dans les langage utilisant le type erasure je ne demande qu'a apprendre...

+1, le but d'une machine virtuelle est d'exécuter rapidement un programme, voire parfois aussi de gérer au mieux la mémoire... pas de faciliter le travail de retroingénierie, l'analyse statique du bytecode & cie

D'ailleurs le même reproche peut être fait à .Net dans une moindre mesure (pas les generics, mais le bytecode est bien simplifié à un moment, sinon on ne s'en sortirait pas... ex : essayez le reverse-engineering de bytecode compilé depuis des sources utilisant des dynamics ; idem avec IL et ILX)
Hum... Si encore la JVM était plus rapide que la CLR cela pourrait avoir du sens... type erasure n'a pas pour vocation d'améliorer les performances, et ne facilite pas forcément la traduction du langage en assembleur (bytecode).
Et à mon avis, c'est d'autant plus condamnable pour un langage fortement typé tel que Java... ( et tout les rejetons de la JVM) de supprimer les types lors de la compilation.
0  0