La bibliothèque des collections Scala 2.8 est-elle un cas de «la plus longue note de suicide de l'histoire»? [fermé]

873

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.

oxbow_lakes
la source
10
fud est juste synonyme de peur, d'incertitude et de doute - je pense que exprime très clairement le ton du discours de Josh Bloch que je suis également d'accord pour dire est bien argumenté et raisonné, etc. Si vous voyez les modifications, je n'ai pas mis à l'origine fud parce que Je ne voulais pas impliquer -ve connotations
oxbow_lakes
32
Cette question a été mentionnée dans le discours d'ouverture de Martin Odersky lors des Scala Days 2010 days2010.scala-lang.org/node/136
Binil Thomas
7
Ce que j'aime chez Scala, c'est que vous n'avez pas besoin de comprendre que c'est un système de type complexe pour faire des choses simples et élégantes. sa syntaxe peut être intimidante, mais elle vous assure une chose, il n'y a pas de "magie" par exemple la magie fait partie du langage, c'est une approche très courageuse et intelligente je pense, vous avez un langage qui peut créer de nouveaux DSL et de nouveaux mini langues en soi, oui, avec de mauvaises mains Scala peut être un très bon ajout à votre dîner italien, mais une fois que vous vous y êtes habitué, c'est une langue incroyable
Eran Medan
87
Comment cette question peut-elle être "non constructive" lorsqu'elle a conduit à @MartinOdersky à réévaluer l'utilisabilité de Scala et à faire en sorte que son système de documentation masque les détails du système de type, sans parler d'une discussion éclairante?
Jerry101
14
En effet, SO est uniquement pour la technicité avec le bon format. Si vous avez quelque chose de délicat, intrigant et de grande envergure, veuillez chercher ailleurs. Vive la mentalité bureaucratique.
qed

Réponses:

892

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 mapou collectseraient 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é mapprise en charge par son type compliqué est assez avancée. Considère ceci:

scala> import collection.immutable.BitSet
import collection.immutable.BitSet

scala> val bits = BitSet(1, 2, 3)
bits: scala.collection.immutable.BitSet = BitSet(1, 2, 3)

scala> val shifted = bits map { _ + 1 }
shifted: scala.collection.immutable.BitSet = BitSet(2, 3, 4)

scala> val displayed = bits map { _.toString + "!" }
displayed: scala.collection.immutable.Set[java.lang.String] = Set(1!, 2!, 3!)

Voyez comment vous obtenez toujours le meilleur type possible? Si vous mappez Ints à Ints, vous obtenez à nouveau un BitSet, mais si vous mappez Ints à Strings, vous obtenez un général Set. 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 yeux mapen BitSetelle a obtenu:

map(f: Int => Int): BitSet     (click here for more general type)

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 a mapé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.

Martin Odersky
la source
107
Je me sens comme un écolier coquin! Merci beaucoup d'avoir pris le temps de répondre ici. Je pense que l'équilibre des réponses m'a montré que je n'ai pas à m'inquiéter; il y aura suffisamment de gens qui ne seront pas du tout intimidés.
oxbow_lakes
164
Non, je pense que vous aviez absolument raison de frapper sur ce point. Et d'autres personnes auront peur à moins que nous ne fassions quelque chose.
Martin Odersky
33
Martin, j'aime votre suggestion de montrer une signature de méthode simplifiée et de cacher les détails généraux derrière un lien.
Derek Mahar
18
Je pense qu'une solution qui fonctionnerait au moins aussi bien est plus d'explications dans les documents. Je ne trouverais pas les signatures aussi intimidantes, si ce n'était le fait que la plupart des méthodes (et même la plupart des classes) n'ont pas plus d'une seule phrase décrivant leur objectif et leur fonctionnement.
Nick Johnson
98
Mise à jour: la version finale de Scala 2.8 a un mécanisme comme celui que j'ai décrit. Si vous recherchez BitSet dans les scaladocs, vous trouvez: def map [B] (f: (Int) ⇒ B): BitSet [B] [cas d'utilisation] Construit une nouvelle collection en appliquant une fonction à tous les éléments de ce bitet.
Martin Odersky
226

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 mapfonction que vous avez postée. Cela me semble à peu près la même signature que celle que mapj'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 soit IterableLike, 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, mapn'a pas réellement besoin que la collection soit une liste, soit ordonnée ou triable ou quelque chose comme ça. La seule chose qui mapcompte, 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

map :: (a → b)[a][b]

qui est la signature de type traditionnelle pour map, il est généralisé de ne pas nécessiter une structure concrète Listmais plutôt juste une IterableLikestructure de données

map :: (IterableLike i, IterableLike j)(a → b) → i → j

ce 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:

map :: IterableLike i ⇒ (a → b) → i → ([b] → c) → c

J'avoue que la syntaxe est un peu plus maladroite, mais la sémantique est la même. Fondamentalement, cela commence à partir de

def map[B](f: (A) ⇒ B): List[B]

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 concret Listà un plus général.IterableLike

def map[B](f: (A) ⇒ B): IterableLike[B]

Maintenant, il remplace la IterableLikecollection de résultats par une fonction qui produit , enfin, pratiquement n'importe quoi.

def map[B, That](f: A ⇒ B)(implicit bf: CanBuildFrom[Repr, B, That]): That

Ce que je crois vraiment n'est pas si difficile à comprendre. Il n'y a vraiment que quelques outils intellectuels dont vous avez besoin:

  1. Vous devez savoir (grossièrement) ce qui mapest. 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 qui mapest 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 cela mapprend-il deux fonctions comme arguments, pas une?"
  2. Vous devez être capable de lire réellement la signature de type. Mais même si vous n'avez jamais vu Scala auparavant, cela devrait être assez facile, car il s'agit vraiment d'un mélange de syntaxes de types que vous connaissez déjà dans d'autres langages: VB.NET utilise des crochets pour le polymorphisme paramétrique, et en utilisant une flèche pour indiquer la retourner le type et deux points pour séparer le nom et le type est en fait la norme.
  3. Vous devez savoir à peu près ce qu'est la programmation générique. (Ce qui n'est pas si difficile à comprendre, car tout est essentiellement énoncé dans le nom: c'est juste une programmation générique).

Aucun de ces trois ne devrait donner à un programmeur professionnel ou même amateur un mal de tête sérieux. mapa é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.

Jörg W Mittag
la source
36
@Jorg - c'est une réponse impressionnante; Merci. Que vous ayez un diplôme ou non, vous êtes un homme plus brillant que moi. Le seul petit reproche que je fais, c'est que je comprends la vue d' ensemble de ce qui se passe dans la signature de la méthode. Cependant, les détails sont toujours confus: comment est That-il déduit et lié au type Bé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!
oxbow_lakes
50
Belle explication, mais vous m'avez encore plus convaincu que la signature de la méthode Scala 2.8 "map" est très compliquée.
Derek Mahar
11
Un langage qui ressemble à ceci: def map [B] (f: (A) ⇒ B): IterableLike [B] est beaucoup plus invitant qu'un langage qui ressemble à ceci: def map [B, That] (f: A ⇒ B ) (bf implicite: CanBuildFrom [Repr, B, That]): That
Mark Essel
215
Je trouve assez intéressant que vous commenciez par affirmer que vous ne connaissiez que les notions de base, de rubis et de petite conversation, et que vous continuiez de n'avoir aucune formation universitaire en la matière. ... puis revendiquant plus tard des connaissances sur la complexité des systèmes de types dans des langages tels que Miranda et Clean; langages principalement connus que parmi les geeks et les universitaires de langages de programmation sérieux.
Sami
14
Vous avez un point valide que la comparaison avec Haskell est incorrecte dans la mesure où "map :: (a -> b) -> [a] -> [b]" est spécifique aux listes. Cependant, la version généralisée, celle de la classe Functor, est encore beaucoup plus simple que la version Scala: classe Functor f où fmap :: (a -> b) -> fa -> fb
Orclev
175

Même chose en C ++ :

template <template <class, class> class C,
          class T,
          class A,
          class T_return,
          class T_arg
              >
C<T_return, typename A::rebind<T_return>::other>
map(C<T, A> &c,T_return(*func)(T_arg) )
{
    C<T_return, typename A::rebind<T_return>::other> res;
    for ( C<T,A>::iterator it=c.begin() ; it != c.end(); it++ ){
        res.push_back(func(*it));
    }
    return res;
}
skyde
la source
105
... et ils disent que Scala est obscure. Duh!
missingfaktor
24
Imaginez à quoi cela aurait ressemblé si des identifiants auto-descriptifs appropriés avaient été utilisés à la place de majuscules arbitraires. :-)
Ti Strga
14
Il est utile de voir cette comparaison, mais il serait plus juste si l'implémentation était omise.
Aaron Novstrup
2
Je ne suis pas un grand fan du pointeur de fonction obligatoire. De toute évidence, le type de funcdoit être un paramètre de modèle, et vous devez utiliser result_ofet is_callablepour obtenir les autres types et contraindre le jeu de surcharge de manière appropriée :-)
Kerrek SB
1
mes yeux me font mal !!!
Ashkan Kh. Nazary
71

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:

  1. 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.

  2. 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.

  3. À 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.

  4. 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.

Daniel C. Sobral
la source
10
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.
gamliela
9
@gamliela, je ne pense pas que nous serons tristes à ce sujet. La connaissance a toujours plus d'un niveau à appliquer, et le travail et la confiance des autres (évalués par les pairs) dans n'importe quel système peuvent toujours être mis à profit, tout comme nous utilisons quotidiennement l'arithmétique et ignorons totalement les algèbres effrayantes qui travaillent derrière.
lcn
55

Est-ce que cela va dissuader les gens de venir à Scala?

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.

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?

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.

La restructuration de la bibliothèque était-elle une idée sensée?

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.

Si vous utilisez scala dans le commerce, êtes-vous inquiet à ce sujet? Envisagez-vous d'adopter la version 2.8 immédiatement ou attendez de voir ce qui se passe?

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.

Erik Engbrecht
la source
31
"cela empêchera également les gens d'être renvoyés". cette. absolument. scala est le premier langage qui fait de l'ingénierie avec quelque chose de comparable à haskell (au pouvoir de son système de type) une possibilité pour beaucoup d'entre nous. il n'y a aucun moyen de convaincre le travail d'utiliser haskell, mais scala a vraiment une chance et pour cela je l'aime et je vais (quand je pense que cela a du sens) essayer de le faire adopter, ou du moins accepté, au travail.
Andrew Cooke,
+1 de moi aussi. Étant donné la prémisse que Scala met davantage l'accent sur la profondeur et la rigueur linguistiques que sur l'accessibilité de masse, ces réponses correspondent parfaitement.
Carl Smotricz
16
"Les développeurs grand public de demain utiliseront le langage utilisé par les développeurs de nouvelles applications les plus performants d'aujourd'hui." +1. Brillamment dit.
Vasil Remeniuk
46

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.

Derek Mahar
la source
43

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'il Intne 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.

Carl Smotricz
la source
9
Désolé pour tous les commentaires. 1 semaine est une blague pour pratiquement n'importe quelle langue, mais cela n'empêche pas les managers de mettre cette blague en pratique. On m'a donné une fois 3 jours pour "former" un groupe de développeurs C ++ en Java. J'ai demandé 5 jours mais j'ai été court-circuité pour des raisons budgétaires.
Carl Smotricz
22
Pour mon premier emploi, j'ai reçu un livre C ++ à la fin de l'entretien pour apprendre avant de commencer à travailler le lundi. Vous êtes tous des wusses.
Tom Hawtin - tackline
12
@Tom @Erik Les garçons, c'est facile. On m'a donné les schémas de circuit de l'ordinateur (pas de CPU à l'époque), et on m'a dit que j'avais deux heures pour corriger un bug lors de l'entretien.
Daniel
33
@Daniel @Tom @Erik On m'a donné une fois un 0 et un 1 et on m'a demandé de les utiliser pour résoudre le problème du sac à dos en temps linéaire pendant l'entretien. Je lui ai donné un coup mais malheureusement je n'ai eu que le temps de créer Eclipse (que je soupçonne être réductible au sac à dos). #tall_tale
Alex Miller
10
@Alex Cela montre un manque d'imagination. Placez un grand zéro à gauche et deux autres petits zéros à sa droite: l'un au-dessus de l'autre, le haut légèrement à gauche. Placez celui entre ces deux petits zéros, en allant du coin inférieur gauche au coin supérieur droit. Disons que c'est la chance de résoudre le sac à dos en temps linéaire. Voilà, vous avez terminé. :-) +1 pour assimiler Eclipse et Knapsack, cependant. :-)
Daniel C. Sobral
33

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 à CanBuildFrommê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 type Bdans le type de retour That» aiderait un peu, mais il est un peu un concept enivrant quand tout ce que vous voulez vraiment faire est la carte Aest à B's. En fait, je ne suis pas sûr que ce soit vrai, car je ne sais pas ce que le type Reprsignifie, et la documentation pour Traversablene donne certainement aucun indice.

Donc, je me retrouve avec deux options, aucune d'elles n'est agréable:

  • Supposons que cela fonctionnera simplement comment fonctionne l'ancienne carte et comment la carte fonctionne dans la plupart des autres langues
  • Creusez un peu plus dans le code source

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.

davetron5000
la source
2
Represt la représentation traversable, ie. Listou Setou Map. 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'utilisation
oxbow_lakes
10
Alors, comment aurais-je pu déterminer ce Reprque 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 (regardez Actor.reactet Actor.receive- on m'a dit, et j'ai vu, qu'ils font des choses totalement différentes, mais leur scaladoc est identique).
davetron5000
7
Je suis d'accord avec davetron5000. Je connais assez bien Scala mais les définitions implicites me font encore mal à la tête. Et la raison n'est pas implicite en soi mais comment ils sont utilisés. Il devrait certainement y avoir une meilleure documentation et un meilleur support d'outils pour comprendre les types Scala. Cela dit, je pense que le système de type a vraiment quelque chose d'important à offrir. Mais nous ne sommes encore qu'au début du chemin de la programmation sensée.
egaga
22

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:

Map(1 -> "a", 2 -> "b").map((t) => (t._2) -> (t._1)) // returns Map("a" -> 1, "b" -> 2)
Map(1 -> "a", 2 -> "b").map((t) =>  t._2)            // returns List("a", "b")

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.

Thomas Heywood
la source
20

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:

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

Je vais le convertir en Scala:

def traverse[A, B](f: A => F[B], a: T[A])(implicit t: Traversable[T], ap: Applicative[F]): F[T[B]

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.

Tony Morris
la source
3
Salut Tony - merci pour votre contribution réfléchie ici. J'y ferais 2 réponses. Le premier est que je n'ai pas mentionné le "programmeur moyen" et je ne pense pas que Scala en soit nécessairement un. Que ce soit vaniteux ou autre, je crois que je suis au-dessus de la moyenne; cependant, je pense toujours que la signature de type est intimidante! En d'autres termes, je crains toujours que les programmeurs supérieurs à la moyenne, le marché cible de Scala, ne soient chassés.
oxbow_lakes
6
Le deuxième point est que je suis fondamentalement en désaccord avec vous sur ce que Scala est : Scala est un langage pragmatique - pas une théorie pure. Sinon, pourquoi aurait-il été conçu au sommet de la machine virtuelle Java? Il s'agit d'une décision purement pragmatique - elle s'adresse aux développeurs «dans le monde réel» - un choix qui a peut-être nécessité des compromis! Notez également que Bloch et Yegge sont loin des programmeurs moyens - mais c'est mon point. Même des personnes très respectées et intelligentes peuvent avoir des opinions sur la complexité et la pureté qui diffèrent des vôtres. Malheureusement pour vous, ils sont également très influents.
oxbow_lakes
3
Bonjour oxbow_lakes, C'est un objectif déclaré de Scala d'apaiser les programmeurs typiques, même au détriment de la précision et de la praticité. Les programmeurs supérieurs à la moyenne sont chassés (j'ai plusieurs anecdotes), mais pas parce que les signatures de type sont intimidantes, mais à cause de la nature de certaines des erreurs. Je n'ai pas dit que Scala est ou n'est pas pragmatique ou théorique. De plus, je ne souscris même pas à l'idée (courante?) Qu'une telle dichotomie existe. Les bibliothèques Scala ont vissé la signature de la carte. Je travaille autour des erreurs de Scala depuis des années maintenant; en particulier les bibliothèques. Il est temps de recommencer.
Tony Morris,
5
Je ne considère pas Bloch ou Yegge comme très respecté ou intelligent, mais ils sont en effet assez influents. Oui, c'est regrettable.
Tony Morris,
9
Pourquoi associez-vous traverse à la signature étendue de Scala? La carte de Scala, pour les monofoncteurs, est la fmap standard. Mais ni BitSet ni Map [A, B] ne sont des monofoncteurs, pourtant map a sur eux une définition significative. C'est la motivation de la signature de Scala, et traverse ne résout pas ce problème. Pourquoi la généralité est-elle une mauvaise chose? Les foncteurs applicatifs suivent les effets, quel est leur intérêt dans Scala? Enfin, je crois que la carte générique de Scala peut être implémentée en termes de cheminement généralisé, acceptant un CanBuildFrom et renvoyant un Traversable potentiellement différent: pas besoin de sacrifier pour les compréhensions!
Blaisorblade
15

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 ...

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

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 à ...

def map(f: A => B): That

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...

def map.(f: A => B).: That

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 ...

def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

Maintenant, si nous avons caché la déclaration générique, c'est plus facile à lire

def orElse(that: PartialFunction[A1, B1]): PartialFunction[A1, B1]

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.

James Strachan
la source
5
Mais que signifie "Cela" comme type de résultat?
Blaisorblade
11

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.)

Peter Mortensen
la source
22
Je pense qu'il veut savoir si les personnes sans doctorat de Cambridge peuvent gérer Scala 2.8.
Ken Bloom
2
Haha: touche! Eh bien, j'ai dit que scala 2.8 est facile à utiliser - ma question était plutôt de savoir à quoi cela ressemblerait pour quelqu'un parcourant l'API pour voir s'il l'aimait, en supposant qu'il n'avait aucune expérience préalable dans Scala.
oxbow_lakes
1
@andrew - d'après l'apparence de votre site Web ( acooke.org ), vous n'êtes pas mal à l'aise avec des concepts visuellement intimidants
oxbow_lakes
Quiconque s'occupe de la programmation de Malbolge, même s'il ne s'agit que de «Hello» Hello World, ne risque d'être intimidé par rien.
Carl Smotricz
10

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.

Jeff G
la source
5
Il ne s'agit jamais de notation (ou jamais plus que, disons, de 10 à 15% de notation), il s'agit toujours de concepts. Et si vous êtes raisonnablement intelligent et que vous n'êtes pas enlisé dans des décennies de connaissances issues de modèles différents, peut-être contradictoires (comme je le suis probablement), il n'est généralement pas trop difficile de saisir ces choses. Mais si vous êtes imprégné d'une façon de penser et de faire les choses, alors c'est au moins un effort d'adaptation et beaucoup réagissent contre de tels changements. C'est juste de la psychologie / nature humaine. (Je me demande comment la psychologie de la programmation informatique de Weinberg résiste après près de 40 ans?)
Randall Schulz
1
@Randall Schultz et Jeff G: La syntaxe / notation est relativement facile à gérer pour une personne intelligente. Différents noms pour les mêmes concepts, en gros. Se familiariser avec une nouvelle langue n'est qu'une question de pratique. TOUTEFOIS, l'étape de la programmation procédurale à la programmation fonctionnelle est ... d'une largeur effrayante. C'est vraiment une façon de penser différente. J'ai essayé Clojure depuis quelques mois et je trouve que c'est un langage FP relativement "facile" et agréable. Mais j'ai encore besoin de beaucoup de temps pour trouver des choses qui seraient simples dans la programmation procédurale.
Carl Smotricz
7

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.

Ken Bloom
la source
Oui, la syntaxe de la vue rend la chose plus rapide à saisir.
egaga
6

Est-ce que cela va dissuader les gens de venir à Scala?

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.

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?

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.

La restructuration de la bibliothèque était-elle une idée sensée?

Absolument.

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?

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.

  1. 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.

  2. 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.

Shelby Moore III
la source
Alors, votre langage va-t-il être orienté objet?
missingfaktor
Oui, hérite du système de type de Scala. Une distinction clé est que le trait est divisé en interface et mixin, où l'interface ne contient que des signatures de méthode et aucune implémentation. Et seule une interface peut être référencée en tant que type. Les implicites sont éliminés et les classes de type sont traitées de manière SPOT dans l'interface. Voici un brouillon de détails. Les collaborateurs sont les bienvenus. Un code pour la bibliothèque est ici . C'est un travail en cours, excuses pour avoir mentionné vaporware. Je partage juste des pensées.
Shelby Moore III du
5

Il semble nécessaire d'indiquer ici un diplôme: BA en science politique et B.ED en informatique.

Jusqu'au point:

Est-ce que cela va dissuader les gens de venir à Scala?

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.

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?

Je ne serais pas inquiet.

Julian Dehne
la source
4

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.

Mat
la source
-1

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.

Sujen
la source
Mais l'un des principaux points est la différence entre la bibliothèque du point de vue d'un utilisateur et des créateurs. De toute évidence, les créateurs ont besoin d'une compréhension impressionnante des fonctionnalités linguistiques requises (par exemple, les types de type supérieur, la priorité implicite) - la question est: "les utilisateurs?"
oxbow_lakes