Je viens de commencer à regarder la ré-implémentation de la bibliothèque des collections Scala qui arrive dans la version 2.8 imminente . Ceux qui connaissent la bibliothèque à partir de 2.7 remarqueront que la bibliothèque, du point de vue de l'utilisation, a peu changé. Par exemple...
> List("Paris", "London").map(_.length)
res0: List[Int] List(5, 6)
... fonctionnerait dans les deux versions. La bibliothèque est éminemment utilisable : en fait c'est fantastique. Cependant, ceux qui ne connaissaient pas encore Scala et qui cherchent à comprendre le langage doivent maintenant donner un sens aux signatures de méthode comme:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Pour une fonctionnalité aussi simple, c'est une signature intimidante et que j'ai du mal à comprendre. Non pas que je pense que Scala ait jamais été le prochain Java (ou / C / C ++ / C #) - je ne crois pas que ses créateurs le visaient sur ce marché - mais je pense qu'il est / était certainement possible pour Scala de devenir le prochain Ruby ou Python (c'est-à-dire pour gagner une importante base d'utilisateurs commerciaux)
- Est-ce que cela va dissuader les gens de venir à Scala?
- Est-ce que cela va donner à Scala une mauvaise réputation dans le monde commercial en tant que jouet académique que seuls les doctorants dédiés peuvent comprendre? Les CTO et les chefs de logiciel vont-ils avoir peur?
- La restructuration de la bibliothèque était-elle une idée sensée?
- Si vous utilisez Scala à des fins commerciales, êtes-vous inquiet à ce sujet? Envisagez-vous d'adopter la version 2.8 immédiatement ou attendez de voir ce qui se passe?
Steve Yegge a une fois attaqué Scala (à tort à mon avis) pour ce qu'il considérait comme son système de type trop compliqué. Je crains que quelqu'un ne passe une journée sur le terrain à diffuser du FUD avec cette API (de la même manière que Josh Bloch a effrayé le JCP d'ajouter des fermetures à Java).
Remarque - Je dois préciser que, même si je pense que Joshua Bloch a influé sur le rejet de la proposition de fermeture de la BGGA, je n'attribue cela à rien d'autre qu'à ses convictions honnêtes selon lesquelles la proposition représentait une erreur.
Malgré tout ce que ma femme et mes collègues continuent de me dire, je ne pense pas que je suis un idiot: j'ai un bon diplôme en mathématiques de l' Université d'Oxford et je programme dans le commerce depuis près de 12 ans et à Scala depuis environ un an (également commercialement).
Notez que le titre du sujet incendiaire est une citation faite au sujet du manifeste d'un parti politique britannique au début des années 1980 . Cette question est subjective mais c'est une vraie question, je l'ai fait CW et j'aimerais avoir des avis sur la question.
la source
Réponses:
J'espère que ce n'est pas une "note de suicide", mais je peux voir votre point. Vous frappez sur ce qui est à la fois une force et un problème de Scala: son extensibilité . Cela nous permet d'implémenter la plupart des fonctionnalités majeures dans les bibliothèques. Dans certains autres langages, des séquences avec quelque chose comme
map
oucollect
seraient intégrées, et personne n'a à voir tous les cerceaux que le compilateur doit traverser pour les faire fonctionner correctement. À Scala, tout est dans une bibliothèque, et donc à l'air libre.En fait, la fonctionnalité
map
prise en charge par son type compliqué est assez avancée. Considère ceci:Voyez comment vous obtenez toujours le meilleur type possible? Si vous mappez
Int
s àInt
s, vous obtenez à nouveau unBitSet
, mais si vous mappezInt
s àString
s, vous obtenez un généralSet
. Le type statique et la représentation d'exécution du résultat de la carte dépendent du type de résultat de la fonction qui lui est transmise. Et cela fonctionne même si l'ensemble est vide, donc la fonction n'est jamais appliquée! Pour autant que je sache, il n'y a pas d'autre cadre de collecte avec une fonctionnalité équivalente. Pourtant, du point de vue de l'utilisateur, c'est ainsi que les choses sont censées fonctionner.Le problème que nous avons, c'est que toute la technologie intelligente qui rend cela possible s'infiltre dans les signatures de type qui deviennent volumineuses et effrayantes. Mais peut-être qu'un utilisateur ne devrait pas voir par défaut la signature de type complet de
map
? Que diriez - vous si elle leva les yeuxmap
enBitSet
elle a obtenu:Les documents ne mentiraient pas dans ce cas, car du point de vue de l'utilisateur, la carte a en effet le type
(Int => Int) => BitSet
. Mais amap
également un type plus général qui peut être inspecté en cliquant sur un autre lien.Nous n'avons pas encore implémenté de telles fonctionnalités dans nos outils. Mais je crois que nous devons le faire, pour éviter de faire peur aux gens et pour donner des informations plus utiles. Avec des outils comme ça, j'espère que les cadres et les bibliothèques intelligents ne deviendront pas des notes de suicide.
la source
Je n'ai pas de doctorat, ni aucun autre type de diplôme ni en CS ni en mathématiques ni d'ailleurs dans aucun autre domaine. Je n'ai aucune expérience préalable avec Scala ni aucune autre langue similaire. Je n'ai aucune expérience avec des systèmes de type comparables à distance. En fait, la seule langue que j'ai plus qu'une connaissance superficielle dont même a un système de type est Pascal, pas exactement connu pour son système de type sophistiqué. (Bien qu'il n'avoir des types de gamme, qui AFAIK à peu près pas d' autre langue a, mais ce n'est pas vraiment ici. Pertinent) Je sais que les trois autres langues sont BASIC, Smalltalk et Ruby, dont aucun n'a même un système de type.
Et pourtant, je n'ai aucun mal à comprendre la signature de la
map
fonction que vous avez postée. Cela me semble à peu près la même signature que celle quemap
j'ai vue dans toutes les autres langues. La différence est que cette version est plus générique. Cela ressemble plus à une chose C ++ STL qu'à, disons, Haskell. En particulier, il s'éloigne du type de collection concret en exigeant uniquement que l'argument soitIterableLike
, et s'abstient également du type de retour concret en exigeant seulement qu'il existe une fonction de conversion implicite qui peut construire quelque chose à partir de cette collection de valeurs de résultat. Oui, c'est assez complexe, mais ce n'est vraiment qu'une expression du paradigme général de la programmation générique: ne supposez rien que vous n'ayez pas à faire.Dans ce cas,
map
n'a pas réellement besoin que la collection soit une liste, soit ordonnée ou triable ou quelque chose comme ça. La seule chose quimap
compte, c'est qu'il puisse accéder à tous les éléments de la collection, l'un après l'autre, mais sans ordre particulier. Et il n'a pas besoin de savoir ce qu'est la collection résultante, il a seulement besoin de savoir comment la construire. C'est donc ce que requiert sa signature de type.Donc, au lieu de
qui est la signature de type traditionnelle pour
map
, il est généralisé de ne pas nécessiter une structure concrèteList
mais plutôt juste uneIterableLike
structure de donnéesce qui est ensuite généralisé en exigeant uniquement l'existence d'une fonction capable de convertir le résultat en la structure de données que l'utilisateur souhaite:
J'avoue que la syntaxe est un peu plus maladroite, mais la sémantique est la même. Fondamentalement, cela commence à partir de
qui est la signature traditionnelle de
map
. (Remarquez qu'en raison de la nature orientée objet de Scala, le paramètre de liste d'entrée disparaît, car c'est maintenant le paramètre récepteur implicite que possède chaque méthode dans un système OO à répartition unique.) Ensuite, il s'est généralisé d'un concretList
à un plus général.IterableLike
Maintenant, il remplace la
IterableLike
collection de résultats par une fonction qui produit , enfin, pratiquement n'importe quoi.Ce que je crois vraiment n'est pas si difficile à comprendre. Il n'y a vraiment que quelques outils intellectuels dont vous avez besoin:
map
est. Si vous ne donniez que la signature de type sans le nom de la méthode, je l'admets, il serait beaucoup plus difficile de comprendre ce qui se passe. Mais puisque vous savez déjà ce quimap
est censé faire, et que vous savez ce que sa signature de type est censée être, vous pouvez rapidement scanner la signature et vous concentrer sur les anomalies, comme "pourquoi celamap
prend-il deux fonctions comme arguments, pas une?"Aucun de ces trois ne devrait donner à un programmeur professionnel ou même amateur un mal de tête sérieux.
map
a été une fonction standard dans à peu près tous les langages conçus au cours des 50 dernières années, le fait que différentes langues ont une syntaxe différente devrait être évident pour quiconque a conçu un site Web avec HTML et CSS et vous ne pouvez pas vous abonner à une programmation même à distance. liste de diffusion connexe sans fanboy C ++ ennuyeux de l'église de St. Stepanov expliquant les vertus de la programmation générique.Oui, Scala est complexe. Oui, Scala possède l'un des systèmes de types les plus sophistiqués connus de l'homme, rivalisant et même dépassant les langues comme Haskell, Miranda, Clean ou Cyclone. Mais si la complexité était un argument contre le succès d'un langage de programmation, C ++ serait mort depuis longtemps et nous serions tous en train d'écrire Scheme. Il y a de nombreuses raisons pour lesquelles Scala ne réussira probablement pas, mais le fait que les programmeurs ne puissent pas être dérangés pour tourner la tête avant de s'asseoir devant le clavier ne sera probablement pas le principal.
la source
That
-il déduit et lié au typeB
étant une question qui vient à l'esprit. D'où viennent les implications d'une autre. Même sans ces observations détaillées, je pense toujours personnellement qu'il s'agit d'une signature complexe. Mais évidemment, il y a des gens comme vous là-bas qui ne sont pas du tout déroutés par cela!Même chose en C ++ :
la source
func
doit être un paramètre de modèle, et vous devez utiliserresult_of
etis_callable
pour obtenir les autres types et contraindre le jeu de surcharge de manière appropriée :-)Eh bien, je peux comprendre votre douleur, mais, franchement, des gens comme vous et moi - ou à peu près n'importe quel utilisateur régulier de Stack Overflow - ne sont pas la règle.
Ce que je veux dire par là, c'est que ... la plupart des programmeurs ne se soucient pas de cette signature de type, car ils ne les verront jamais ! Ils ne lisent pas la documentation.
Tant qu'ils ont vu un exemple du fonctionnement du code et que le code ne leur fait pas échec dans la production du résultat attendu , ils ne consulteront jamais la documentation. En cas d'échec, ils examineront la documentation et s'attendront à voir des exemples d'utilisation en haut.
Avec ces choses à l'esprit, je pense que:
Quiconque (comme dans la plupart des gens) qui rencontre cette signature de type se moquera de Scala sans fin s'il est prédisposé contre elle, et le considérera comme un symbole du pouvoir de Scala s'il aime Scala.
Si la documentation n'est pas améliorée pour fournir des exemples d'utilisation et expliquer clairement à quoi sert une méthode et comment l'utiliser, cela peut nuire un peu à l'adoption de Scala.
À long terme, cela n'aura pas d'importance. Que Scala puisse faire des choses comme ça rendra les bibliothèques écrites pour Scala beaucoup plus puissantes et plus sûres à utiliser. Ces bibliothèques et cadres attireront les programmeurs attirés par des outils puissants.
Les programmeurs qui aiment la simplicité et la franchise continueront d'utiliser PHP ou des langages similaires.
Hélas, les programmeurs Java aiment beaucoup les outils électriques, donc, en répondant à cela, je viens de réviser mes attentes en matière d'adoption de Scala. Je n'ai aucun doute que Scala deviendra une langue dominante. Pas C-mainstream, mais peut-être Perl-mainstream ou PHP-mainstream.
En parlant de Java, avez-vous déjà remplacé le chargeur de classe? Avez-vous déjà examiné ce que cela implique? Java peut faire peur, si vous regardez les endroits où les rédacteurs de frameworks le font. C'est juste que la plupart des gens ne le font pas. La même chose s'applique à Scala, à mon humble avis, mais les premiers utilisateurs ont tendance à regarder sous chaque rocher qu'ils rencontrent, pour voir s'il y a quelque chose qui s'y cache.
la source
As long as they saw some example of how the code works, and the code doesn't fail them in producing the result they expect, they won't ever look at the documentation. When that fails, they'll look at the documentation and expect to see usage examples at the top.
Triste mais vrai.Oui, mais cela empêchera également les gens d'être renvoyés. J'ai considéré le manque de collections qui utilisent des types de type supérieur comme une faiblesse majeure depuis que Scala a pris en charge les types de type supérieur. Cela rend les documents API plus compliqués, mais cela rend vraiment l'utilisation plus naturelle.
Certains le feront probablement. Je ne pense pas que Scala soit accessible à de nombreux développeurs "professionnels", en partie à cause de la complexité de Scala et en partie à cause de la réticence de nombreux développeurs à apprendre. Les CTO qui emploient de tels développeurs seront à juste titre effrayés.
Absolument. Cela rend les collections bien mieux adaptées au reste de la langue et du système de type, même si elle a encore des bords rugueux.
Je ne l'utilise pas commercialement. J'attendrai probablement au moins quelques tours dans la série 2.8.x avant même d'essayer de l'introduire pour que les bugs puissent être éliminés. J'attendrai également le succès de l'EPFL dans l'amélioration de ses processus de développement et de sortie. Ce que je vois semble plein d'espoir, mais je travaille pour une entreprise conservatrice.
L'un des sujets les plus généraux de "Scala est-il trop compliqué pour les développeurs grand public?" ...
La plupart des développeurs, grand public ou non, maintiennent ou étendent les systèmes existants. Cela signifie que la plupart de ce qu'ils utilisent est dicté par des décisions prises il y a longtemps. Il y a encore beaucoup de gens qui écrivent COBOL.
Le développeur grand public de demain travaillera à la maintenance et à l'extension des applications en cours de construction. Beaucoup de ces applications ne sont pas construites par des développeurs traditionnels. Les développeurs grand public de demain utiliseront le langage utilisé par les développeurs de nouvelles applications les plus performants d'aujourd'hui.
la source
La communauté Scala peut aider la peur des programmeurs débutants à Scala à se concentrer sur la pratique et à enseigner par l'exemple - de nombreux exemples qui commencent petit et grandissent progressivement. Voici quelques sites qui adoptent cette approche:
Après avoir passé un peu de temps sur ces sites, on se rend vite compte que Scala et ses bibliothèques, bien que peut-être difficiles à concevoir et à implémenter, ne sont pas si difficiles à utiliser, surtout dans les cas les plus courants.
la source
J'ai un diplôme de premier cycle d'une université américaine bon marché "de masse", donc je dirais que je tombe au milieu de l'échelle de l'intelligence utilisateur (ou du moins de l'éducation) :) Je barbotais avec Scala depuis quelques mois seulement et ont travaillé sur deux ou trois applications non triviales.
Surtout maintenant qu'IntelliJ a publié son excellent IDE avec ce que IMHO est actuellement le meilleur plugin Scala, le développement de Scala est relativement indolore:
Je trouve que je peux utiliser Scala comme un "Java sans point-virgule", c'est-à-dire que j'écris un code d'apparence similaire à ce que je ferais en Java, et bénéficie un peu de la brièveté syntaxique telle que celle obtenue par l'inférence de type. La gestion des exceptions, quand je le fais, est plus pratique. La définition de classe est beaucoup moins détaillée sans le passe-partout getter / setter.
De temps en temps, j'arrive à écrire une seule ligne pour accomplir l'équivalent de plusieurs lignes de Java. Le cas échéant, les chaînes de méthodes fonctionnelles telles que cartographier, plier, collecter, filtrer, etc. sont amusantes à composer et élégantes à voir.
Ce n'est que rarement que je me retrouve à bénéficier des fonctionnalités plus puissantes de Scala: fermetures et fonctions partielles (ou curry), correspondance de motifs ... ce genre de chose.
En tant que débutant, je continue de lutter avec la syntaxe laconique et idiomatique. Les appels de méthode sans paramètres n'ont pas besoin de parenthèses, sauf lorsqu'ils le font; les cas dans la déclaration de correspondance ont besoin d'une grosse flèche (
=>
), mais il y a aussi des endroits où vous avez besoin d'une fine flèche (->
). De nombreuses méthodes ont des noms courts mais plutôt cryptiques comme/:
ou\:
- je peux faire mon travail si je retourne suffisamment de pages de manuel, mais une partie de mon code finit par ressembler à Perl ou au bruit de ligne. Ironiquement, l'un des morceaux de raccourci syntaxique les plus populaires manque dans l'action: je continue à être mordu par le fait qu'ilInt
ne définit pas un++
méthode.C'est juste mon opinion: j'ai l'impression que Scala a la puissance du C ++ combinée à la complexité et la lisibilité du C ++. La complexité syntaxique du langage rend également la documentation de l'API difficile à lire.
Scala est très bien pensé et brillant à bien des égards. Je soupçonne que beaucoup d'universitaires aimeraient y programmer. Cependant, il est également plein d'intelligence et de pièges, il a une courbe d'apprentissage beaucoup plus élevée que Java et est plus difficile à lire. Si je scanne les forums et vois combien de développeurs ont encore du mal avec les points les plus fins de Java, je ne peux pas imaginer que Scala devienne un langage courant . Aucune entreprise ne pourra justifier l'envoi de ses développeurs sur un cours Scala de 3 semaines alors qu'auparavant ils n'avaient besoin que d'un cours Java d'une semaine.
la source
Je pense que le principal problème avec cette méthode est qu'elle
(implicit bf : CanBuildFrom[Repr, B, That])
va sans aucune explication. Même si je sais quels sont les arguments implicites, rien n'indique comment cela affecte l'appel. Chasser à travers le scaladoc ne me laisse que plus confus (peu de classes liées àCanBuildFrom
même avoir de la documentation).Je pense qu'un simple "il doit y avoir un objet implicite dans la portée de
bf
qui fournit un constructeur pour les objets de typeB
dans le type de retourThat
» aiderait un peu, mais il est un peu un concept enivrant quand tout ce que vous voulez vraiment faire est la carteA
est àB
's. En fait, je ne suis pas sûr que ce soit vrai, car je ne sais pas ce que le typeRepr
signifie, et la documentation pourTraversable
ne donne certainement aucun indice.Donc, je me retrouve avec deux options, aucune d'elles n'est agréable:
Je comprends que Scala expose essentiellement les entrailles de la façon dont ces choses fonctionnent et qu'en fin de compte, c'est un moyen de faire ce que oxbow_lakes décrit. Mais c'est une distraction dans la signature.
la source
Repr
est la représentation traversable, ie.List
ouSet
ouMap
. Je pense que, comme cadre, si vous allez commencer à regarder les signatures de méthode (plutôt que de simplement utiliser les méthodes en copiant des exemples), vous devez d'abord comprendre la conception générale. À mon humble avis, le Scaladoc devrait être plein d'exemples d'utilisationRepr
que cela signifiait? Je m'attendrais à une explication dans le scaladoc, mais ce n'était vraiment pas évident pour moi. Je pense que c'est un modèle courant dans le scaladoc (regardezActor.react
etActor.receive
- on m'a dit, et j'ai vu, qu'ils font des choses totalement différentes, mais leur scaladoc est identique).Je suis un débutant Scala et honnêtement, je ne vois aucun problème avec cette signature de type. Le paramètre est la fonction à mapper et le paramètre implicite le générateur pour renvoyer la collection correcte. Clair et lisible.
Le tout est assez élégant, en fait. Les paramètres de type de générateur permettent au compilateur de choisir le type de retour correct tandis que le mécanisme de paramètre implicite masque ce paramètre supplémentaire à l'utilisateur de classe. J'ai essayé ceci:
C'est du polymorphisme bien fait.
Maintenant, d'accord, ce n'est pas un paradigme dominant et cela en effraiera beaucoup. Mais, elle attirera également de nombreuses personnes qui apprécient son expressivité et son élégance.
la source
Malheureusement, la signature de la carte que vous avez donnée est incorrecte pour la carte et il y a en effet des critiques légitimes.
La première critique est qu'en renversant la signature de la carte, nous avons quelque chose de plus général. C'est une erreur courante de croire qu'il s'agit d'une vertu par défaut. Ça ne l'est pas. La fonction de carte est très bien définie comme un foncteur covariant Fx -> (x -> y) -> Fy en respectant les deux lois de composition et d'identité. Tout autre élément attribué à la "carte" est une parodie.
La signature donnée est autre chose, mais ce n'est pas une carte. Ce que je soupçonne qu'il essaie d'être, c'est une version spécialisée et légèrement modifiée de la signature "traverse" du document, L'essence du modèle d'itérateur. Voici sa signature:
Je vais le convertir en Scala:
Bien sûr, cela échoue - ce n'est pas assez général! En outre, il est légèrement différent (notez que vous pouvez obtenir la carte en exécutant traverse via le foncteur d'identité). Cependant, je soupçonne que si les rédacteurs de bibliothèque étaient plus conscients des généralisations de bibliothèque qui sont bien documentées (la programmation applicative avec effets précède ce qui précède), nous ne verrions pas cette erreur.
Deuxièmement, la fonction de carte est un cas spécial dans Scala en raison de son utilisation dans les for-comprehensions. Cela signifie malheureusement qu'un concepteur de bibliothèque mieux équipé ne peut ignorer cette erreur sans pour autant sacrifier le sucre syntaxique des compréhensions. En d'autres termes, si les concepteurs de la bibliothèque Scala devaient détruire une méthode, cela est facilement ignoré, mais veuillez ne pas cartographier!
J'espère que quelqu'un en parlera, car en l'état, il deviendra plus difficile de contourner les erreurs que Scala insiste à faire, apparemment pour des raisons auxquelles j'ai de fortes objections. Autrement dit, la solution aux «objections irresponsables du programmeur moyen (c'est-à-dire trop dur!)» N'est pas de «les apaiser pour leur faciliter la tâche», mais plutôt de fournir des conseils et de l'aide pour devenir de meilleurs programmeurs. Les objectifs de moi-même et de Scala sont en désaccord sur cette question, mais revenons à votre point.
Vous étiez probablement en train de faire valoir votre point de vue, en prédisant des réponses spécifiques du "programmeur moyen". Autrement dit, les gens qui réclameront "mais c'est trop compliqué!" ou certains tels. Ce sont les Yegges ou Blochs auxquels vous faites référence. Ma réponse à ces gens du mouvement anti-intellectualisme / pragmatisme est assez dure et j'anticipe déjà un déluge de réponses, donc je vais l'omettre.
J'espère vraiment que les bibliothèques Scala s'améliorent, ou du moins, que les erreurs peuvent être cachées en toute sécurité dans un coin. Java est un langage où «essayer de faire quelque chose d'utile» est si incroyablement coûteux, qu'il n'en vaut souvent pas la peine, car la quantité écrasante d'erreurs ne peut tout simplement pas être évitée. J'implore Scala de ne pas suivre le même chemin.
la source
Je suis totalement d'accord avec la question et la réponse de Martin :). Même en Java, la lecture de javadoc avec des génériques est beaucoup plus difficile qu'elle ne devrait l'être en raison du bruit supplémentaire. Ceci est aggravé dans Scala où les paramètres implicites sont utilisés comme dans l'exemple de code des questions (tandis que les implicits font des trucs de morphing de collection très utiles).
Je ne pense pas que ce soit un problème avec la langue en soi - je pense que c'est plus un problème d'outillage. Et même si je suis d'accord avec ce que dit Jörg W Mittag, je pense qu'en regardant scaladoc (ou la documentation d'un type dans votre IDE) - cela devrait nécessiter le moins de cerveau possible pour comprendre ce qu'est une méthode, ce qu'elle prend et retourne. Il ne devrait pas être nécessaire de pirater un peu d'algèbre sur un peu de papier pour l'obtenir :)
Pour sûr, les IDE ont besoin d'une belle façon de montrer toutes les méthodes pour n'importe quelle variable / expression / type (qui, comme dans l'exemple de Martin, peut avoir tous les génériques en ligne, donc c'est agréable et facile à gérer). J'aime aussi l'idée de Martin de cacher les implicites par défaut.
Pour prendre l'exemple dans scaladoc ...
En regardant cela dans scaladoc, j'aimerais que le bloc générique [B, That] soit caché par défaut ainsi que le paramètre implicite (peut-être qu'ils s'affichent si vous survolez une petite icône avec la souris) - comme élément supplémentaire à grok le lire, ce qui n'est généralement pas si pertinent. par exemple, imaginez si cela ressemblait à ...
agréable et clair et évident ce qu'il fait. Vous pourriez vous demander ce qu'est «That», si vous passez la souris dessus ou cliquez dessus, cela pourrait développer le texte [B, That] en mettant en évidence le «That» par exemple.
Peut-être qu'une petite icône pourrait être utilisée pour la déclaration [] et le bloc (implicite ...) afin qu'il soit clair qu'il y a de petits morceaux de l'instruction effondrés? Il est difficile d'utiliser un jeton pour cela, mais je vais utiliser un. pour l'instant...
Ainsi, par défaut, le «bruit» du système de type est caché aux 80% principaux de ce que les gens doivent regarder - le nom de la méthode, ses types de paramètres et son type de retour de manière simple et concise - avec peu de liens extensibles vers le détail si vous vous souciez vraiment de ça.
La plupart du temps, les gens lisent scaladoc pour savoir quelles méthodes ils peuvent appeler sur un type et quels paramètres ils peuvent passer. Nous sommes en train de surcharger les utilisateurs avec beaucoup trop de détails sur la façon dont à mon humble avis.
Voici un autre exemple ...
Maintenant, si nous avons caché la déclaration générique, c'est plus facile à lire
Ensuite, si les gens survolent, disons A1, nous pourrions montrer que A1 est A1 <: A. Les types covariants et contravariants dans les génériques ajoutent également beaucoup de bruit qui peut être rendu d'une manière beaucoup plus facile à comprendre pour les utilisateurs, je pense.
la source
Je ne sais pas comment vous l'expliquer, mais j'ai un doctorat de Cambridge, et j'utilise 2.8 très bien.
Plus sérieusement, je n'ai pratiquement pas passé de temps avec 2.7 (il n'interagira pas avec une bibliothèque Java que j'utilise) et j'ai commencé à utiliser Scala il y a un peu plus d'un mois. J'ai une certaine expérience avec Haskell (pas beaucoup), mais j'ai simplement ignoré les choses qui vous inquiètent et j'ai cherché des méthodes qui correspondent à mon expérience avec Java (que j'utilise dans la vie).
Donc: je suis un "nouvel utilisateur" et je n'ai pas été découragé - le fait qu'il fonctionne comme Java m'a donné suffisamment de confiance pour ignorer les bits que je ne comprenais pas.
(Cependant, la raison pour laquelle je regardais Scala était en partie de voir s'il fallait le pousser au travail, et je ne le ferai pas encore. Rendre la documentation moins intimidante aiderait certainement, mais ce qui m'a surpris, c'est combien elle est encore changer et être développé (pour être honnête, ce qui m'a le plus surpris, c'est à quel point c'est génial, mais les changements sont venus juste après.) Je suppose donc que je préférerais que les ressources limitées soient consacrées à un état final - je ne pense pas qu'ils s'attendaient à être aussi populaires si tôt.)
la source
Je ne connais pas du tout Scala, mais il y a quelques semaines, je ne pouvais pas lire Clojure. Maintenant, je peux en lire la plupart, mais je ne peux rien écrire encore au-delà des exemples les plus simples . Je suppose que Scala n'est pas différent. Vous avez besoin d'un bon livre ou d'un cours selon la façon dont vous apprenez. Je lis juste la déclaration de la carte ci-dessus, j'ai peut-être 1/3.
Je crois que les plus gros problèmes ne sont pas la syntaxe de ces langages, mais l'adoption et l'internalisation des paradigmes qui les rendent utilisables dans le code de production de tous les jours. Pour moi, Java n'était pas un énorme bond en avant de C ++, qui n'était pas un énorme bond en avant de C, qui n'était pas du tout un bond en avant de Pascal, ni de Basic etc ... Mais le codage dans un langage fonctionnel comme Clojure est un énorme bond en avant (pour moi dans tous les cas). Je suppose que dans Scala, vous pouvez coder en style Java ou en style Scala. Mais dans Clojure, vous créerez tout un désordre en essayant de garder vos habitudes impératives de Java.
la source
Scala a beaucoup de fonctionnalités folles (en particulier en ce qui concerne les paramètres implicites) qui semblent très compliquées et académiques, mais sont conçues pour rendre les choses faciles à utiliser. Les plus utiles obtiennent du sucre syntaxique (comme
[A <% B]
ce qui signifie qu'un objet de type A a une conversion implicite en un objet de type B) et une explication bien documentée de ce qu'ils font. Mais la plupart du temps, en tant que client de ces bibliothèques, vous pouvez ignorer les paramètres implicites et leur faire confiance pour faire la bonne chose.la source
Je ne pense pas que ce soit le principal facteur qui affectera la popularité de Scala, car Scala a beaucoup de puissance et sa syntaxe n'est pas aussi étrangère à un programmeur Java / C ++ / PHP que Haskell, OCaml, SML, Lisps, etc..
Mais je pense que la popularité de Scala atteindra un niveau inférieur à celui de Java aujourd'hui, car je pense également que le prochain langage traditionnel doit être beaucoup plus simplifié, et la seule façon que je vois pour y arriver est l'immuabilité pure, c'est-à-dire déclarative comme HTML, mais Turing complet . Cependant, je suis biaisé parce que je développe un tel langage, mais je ne l'ai fait qu'après avoir exclu au cours d'une étude de plusieurs mois que Scala ne pouvait pas suffire à ce dont j'avais besoin.
Je ne pense pas que la réputation de Scala souffrira du complexe Haskell. Mais je pense que certains retarderont leur apprentissage, car pour la plupart des programmeurs, je ne vois pas encore de cas d'utilisation qui les oblige à utiliser Scala, et ils tergiverseront en l'apprenant. Le côté serveur hautement évolutif est peut-être le cas d'utilisation le plus convaincant.
Et, pour le marché grand public, apprendre d'abord Scala n'est pas une "bouffée d'air frais", où l'on écrit des programmes immédiatement, comme d'abord utiliser HTML ou Python. Scala a tendance à grandir sur vous, après avoir appris tous les détails sur lesquels on trébuche dès le début. Cependant, peut-être que si j'avais lu Programmation dans Scala depuis le début, mon expérience et mon opinion sur la courbe d'apprentissage auraient été différentes.
Absolument.
J'utilise Scala comme plate-forme initiale de ma nouvelle langue. Je ne construirais probablement pas de code sur la bibliothèque de collection de Scala si j'utilisais Scala commercialement autrement. Je créerais ma propre bibliothèque basée sur la théorie des catégories, puisque la seule fois où j'ai regardé, j'ai trouvé les signatures de type de Scalaz encore plus verbeuses et plus maniables que la bibliothèque de collection de Scala. Une partie de ce problème est peut-être la façon dont Scala implémente les classes de types, et c'est une raison mineure pour laquelle je crée mon propre langage.
J'ai décidé d'écrire cette réponse, car je voulais m'obliger à rechercher et comparer le design de la classe de collection de Scala à celui que je fais pour ma langue. Autant partager ma réflexion.
Les collections 2.8 Scala utilisent une abstraction de constructeur est un principe de conception solide. Je veux explorer deux compromis de conception ci-dessous.
CODE ÉCRITURE UNIQUEMENT: Après avoir écrit cette section, j'ai lu le commentaire de Carl Smotricz qui est d'accord avec ce que je pense être le compromis. Les commentaires de James Strachan et davetron5000 s'accordent à dire que le sens de Cela (ce n'est même pas Cela [B]) et le mécanisme de l'implicite n'est pas facile à saisir intuitivement. Voir mon utilisation de monoid dans le numéro 2 ci-dessous, qui je pense est beaucoup plus explicite. Le commentaire de Derek Mahar concerne l'écriture de la scala, mais qu'en est-il de la lecture de la scala des autres qui n'est pas "dans les cas courants".
Une critique que j'ai lue à propos de Scala, c'est qu'il est plus facile de l'écrire que de lire le code que d'autres ont écrit. Et je trouve que cela est parfois vrai pour diverses raisons (par exemple, de nombreuses façons d'écrire une fonction, les fermetures automatiques, l'unité pour les DSL, etc.), mais je ne sais pas si c'est un facteur majeur. Ici, l'utilisation de paramètres de fonction implicites présente des avantages et des inconvénients. Du côté positif, il réduit la verbosité et automatise la sélection de l'objet générateur. Chez Odersky exemplela conversion d'un BitSet, c'est-à-dire Set [Int], en Set [String] est implicite. Le lecteur peu familier du code pourrait ne pas savoir facilement quel est le type de collection, à moins qu'il ne puisse bien raisonner sur tous les candidats potentiels de constructeur implicite invisible qui pourraient exister dans la portée du package actuel. Bien sûr, le programmeur expérimenté et l'auteur du code sauront que BitSet est limité à Int, donc une mappe à String doit être convertie en un type de collection différent. Mais quel type de collection? Il n'est pas spécifié explicitement.
CONCEPTION AD-HOC COLLECTION: Après avoir écrit cette section, j'ai lu le commentaire de Tony Morris et j'ai réalisé que je fais presque le même point. Peut-être que mon exposé plus détaillé rendra le point plus clair.
Dans "Fighting Bit Rot with Types" Odersky & Moors, deux cas d'utilisation sont présentés. Ils sont la restriction de BitSet aux éléments Int et de la carte pour associer les éléments de tuple, et sont fournis comme la raison pour laquelle la fonction de mappage d'élément générale, A => B, doit être capable de créer des types de collection de destination alternatifs. Cependant, afaik cela est défectueux du point de vue de la théorie des catégories. Pour être cohérent dans la théorie des catégories et éviter ainsi les cas d'angle, ces types de collection sont des foncteurs, dans lesquels chaque morphisme, A => B, doit mapper entre les objets de la même catégorie de foncteurs, Liste [A] => Liste [B], BitSet [A] => BitSet [B]. Par exemple, une Option est un foncteur qui peut être vu comme une collection d'ensembles de Some (objet) et None. Il n'y a pas de carte générale de l'option Aucun, ou de la liste Nil, vers d'autres foncteurs qui ne
Un choix de conception de compromis est fait ici. Dans la conception de la bibliothèque de collections de mon nouveau langage, j'ai choisi de faire de tout un foncteur, ce qui signifie que si j'implémente un BitSet, il doit prendre en charge tous les types d'éléments, en utilisant une représentation interne de champ non-bit lorsqu'il est présenté avec un non paramètre de type entier, et cette fonctionnalité est déjà dans l'ensemble dont elle hérite dans Scala. Et Map dans ma conception doit mapper uniquement ses valeurs, et il peut fournir une méthode distincte non fonctor pour mapper ses tuples de paire (clé, valeur). Un avantage est que chaque foncteur est alors généralement aussi un applicatif et peut-être aussi une monade. Ainsi, toutes les fonctions entre les types d'éléments, par exemple A => B => C => D => ..., sont automatiquement levées vers les fonctions entre les types applicatifs levés, par exemple Liste [A] => Liste [B] => Liste [ C] => Liste [D] => .... Pour le mappage d'un foncteur à une autre classe de collection, je propose une surcharge de carte qui prend un monoïde, par exemple Nil, None, 0, "", Array (), etc. Ainsi, la fonction d'abstraction du générateur est la méthode d'ajout d'un monoïde et est fourni explicitement comme paramètre d'entrée nécessaire, donc sans conversions implicites invisibles. (Tangente: ce paramètre d'entrée permet également d'ajouter des monoïdes non vides, ce que la conception de carte de Scala ne peut pas faire.) De telles conversions sont une carte et un pli dans le même passage d'itération. Je propose également un McBride & Patterson "Programmation applicative avec effets", traversable, dans le sens de la catégorie, qui permet également à map + fold en une seule passe d'itération de n'importe quel traversable à n'importe quel applicatif, où la plupart des classes de collection sont les deux.
Donc, afaics, les collections Scala sont "ad hoc" dans le sens où elles ne sont pas fondées sur la théorie des catégories, et la théorie des catégories est l'essence de la sémantique dénotationnelle de niveau supérieur. Bien que les constructeurs implicites de Scala soient à première vue "plus généralisés" qu'un modèle de foncteur + constructeur monoïde + traversable -> applicatif, ils ne semblent pas cohérents avec aucune catégorie, et donc nous ne savons pas quelles règles ils suivent dans le sens le plus général et ce que les cas de coin seront donnés, ils ne peuvent obéir à aucun modèle de catégorie. Il n'est tout simplement pas vrai que l'ajout de variables rend quelque chose de plus général, et c'était l'un des énormes avantages de la théorie des catégories, car elle fournit des règles permettant de maintenir la généralité tout en passant à la sémantique de niveau supérieur. Une collection est une catégorie.
J'ai lu quelque part, je pense que c'était Odersky, comme autre justification de la conception de la bibliothèque, c'est que la programmation dans un style purement fonctionnel a un coût de récursivité et de vitesse limitées là où la récursivité de queue n'est pas utilisée. Je n'ai pas trouvé difficile d'employer la récursivité de queue dans tous les cas que j'ai rencontrés jusqu'à présent.
De plus, je garde dans mon esprit une idée incomplète que certains compromis de Scala sont dus à essayer d'être à la fois un langage mutable et immuable, contrairement par exemple à Haskell ou au langage que je développe. Cela rejoint le commentaire de Tony Morris sur la compréhension. Dans mon langage, il n'y a pas de boucles ni de constructions mutables. Ma langue se trouvera au sommet de Scala (pour l'instant) et lui doit beaucoup, et cela ne serait pas possible si Scala n'avait pas le système de type général et la mutabilité. Ce n'est peut-être pas vrai, car je pense que Odersky & Moors ("Fighting Bit Rot with Types") est incorrect de déclarer que Scala est le seul langage OOP avec des types plus élevés, parce que j'ai vérifié (moi-même et via Bob Harper) que Standard ML les a. Il semble également que le système de types de SML soit flexible de manière équivalente (depuis les années 1980), ce qui peut ne pas être facilement apprécié car la syntaxe n'est pas tellement similaire à Java (et C ++ / PHP) que Scala. En tout cas, ce n'est pas une critique de Scala, mais plutôt une tentative de présenter une analyse incomplète des compromis, ce qui est, je l'espère, pertinent pour la question. Scala et SML ne souffrent pas de l'incapacité de Haskell à fairel'héritage multiple du diamant , ce qui est essentiel et je comprends pourquoi tant de fonctions du Haskell Prelude sont répétées pour différents types.
la source
Il semble nécessaire d'indiquer ici un diplôme: BA en science politique et B.ED en informatique.
Jusqu'au point:
Scala est difficile, car son paradigme de programmation sous-jacent est difficile. La programmation fonctionnelle fait peur à beaucoup de gens. Il est possible de créer des fermetures en PHP mais les gens le font rarement. Donc non, pas cette signature mais tout le reste découragera les gens, s'ils n'ont pas l'éducation spécifique pour leur faire apprécier le pouvoir du paradigme sous-jacent.
Si cette éducation est disponible, tout le monde peut le faire. L'année dernière, j'ai construit un ordinateur d'échecs avec un groupe d'écoliers à SCALA! Ils ont eu leurs problèmes mais ils se sont bien débrouillés au final.
Je ne serais pas inquiet.
la source
J'ai aussi un diplôme de mathématiques d'Oxford! Il m'a fallu un certain temps pour obtenir les nouvelles collections. Mais je l'aime beaucoup maintenant que je le fais. En fait, le fait de taper «map» a été l'une des premières grandes choses qui m'a dérangé en 2.7 (peut-être depuis que la première chose que j'ai faite a été de sous-classer une des classes de collection).
La lecture de l'article de Martin sur les nouvelles collections 2.8 a vraiment aidé à expliquer l'utilisation des implicits, mais oui, la documentation elle-même doit certainement mieux expliquer le rôle des différents types d'implicits dans les signatures de méthode des API principales.
Ma principale préoccupation est la suivante: quand la version 2.8 va-t-elle sortir? Quand les rapports de bogues cesseront-ils de le recevoir? l'équipe scala a-t-elle mordu plus qu'elle ne peut mâcher avec 2,8 / essayé de changer trop à la fois?
J'aimerais vraiment que la version 2.8 soit stabilisée en priorité avant d'ajouter quoi que ce soit de nouveau, et je me demande (tout en regardant de côté) si certaines améliorations pourraient être apportées à la façon dont la feuille de route de développement pour le compilateur scala est gérée.
la source
Qu'en est-il des messages d'erreur sur le site d'utilisation?
Et qu'en est-il du cas d'utilisation, il faut intégrer des types existants à un type personnalisé qui convient à une DSL. Il faut être bien éduqué sur les questions d'association, de priorité, de conversions implicites, de paramètres implicites, de types supérieurs et peut-être de types existentiels.
C'est très bon de savoir que la plupart du temps c'est simple mais ce n'est pas nécessairement suffisant. Au moins, il doit y avoir un gars qui connaît ce genre de choses si une bibliothèque généralisée doit être conçue.
la source