Ich habe gerade angefangen, mir die Neuimplementierung der Scala-Sammlungsbibliothek anzusehen, die in der bevorstehenden Version 2.8 verfügbar sein wird. Diejenigen, die mit der Bibliothek ab 2.7 vertraut sind, werden feststellen, dass sich die Bibliothek aus Sicht der Nutzung kaum verändert hat. Zum Beispiel...
> List("Paris", "London").map(_.length)
res0: List[Int] List(5, 6)
... würde in beiden Versionen funktionieren. Die Bibliothek ist hervorragend nutzbar : Tatsächlich ist sie fantastisch. Diejenigen, die Scala bisher nicht kannten und sich umschauten, um ein Gefühl für die Sprache zu bekommen, müssen nun Methodensignaturen wie:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
Für solch eine einfache Funktionalität ist dies eine entmutigende Signatur, die ich nur schwer verstehen kann. Nicht, dass ich denke, dass Scala jemals das nächste Java (oder / C / C ++ / C #) sein würde - ich glaube nicht, dass seine Entwickler es auf diesen Markt abzielten - aber ich denke, dass es für Scala durchaus machbar ist / war der nächste Ruby oder Python (dh um eine bedeutende kommerzielle Benutzerbasis zu gewinnen)
- Wird dies die Leute davon abhalten, nach Scala zu kommen?
- Wird dies Scala in der Geschäftswelt einen schlechten Ruf als akademisches Spielzeug geben , das nur engagierte Doktoranden verstehen können? Werden CTOs und Leiter von Software Angst bekommen?
- War die Neugestaltung der Bibliothek eine vernünftige Idee?
- Wenn Sie Scala kommerziell nutzen, machen Sie sich darüber Sorgen? Planen Sie die sofortige Einführung von 2.8 oder warten Sie ab, was passiert?
Steve Yegge hat Scala einmal angegriffen (meiner Meinung nach fälschlicherweise), weil er es als sein überkompliziertes Typsystem ansah . Ich mache mir Sorgen, dass jemand einen Feldtag haben wird, an dem FUD mit dieser API verbreitet wird (ähnlich wie Josh Bloch die JCP davon abgehalten hat, Java-Schließungen hinzuzufügen).
Anmerkung - Ich sollte klar sein, dass Joshua Bloch, obwohl ich glaube, dass er Einfluss auf die Ablehnung des BGGA-Schließungsvorschlags hatte, nichts anderes zuschreibt als seine ehrliche Überzeugung, dass der Vorschlag einen Fehler darstellt.
Trotz was meine Frau und Kollegen mich immer wieder sagen, ich glaube nicht , ich bin ein Idiot: Ich habe einen guten Abschluss habe in Mathematik an der University of Oxford , und ich habe die Programmierung im Handel für fast 12 Jahre und in Scala für ca. ein Jahr (auch kommerziell).
Beachten Sie, dass der Titel des entzündlichen Themas ein Zitat über das Manifest einer britischen politischen Partei in den frühen 1980er Jahren ist . Diese Frage ist subjektiv, aber es ist eine echte Frage, ich habe sie CW gemacht und ich hätte gerne einige Meinungen zu diesem Thema.
quelle
Antworten:
Ich hoffe, es ist kein "Abschiedsbrief", aber ich kann Ihren Standpunkt verstehen. Sie treffen auf das, was gleichzeitig eine Stärke und ein Problem von Scala ist: seine Erweiterbarkeit . Auf diese Weise können wir die meisten wichtigen Funktionen in Bibliotheken implementieren. In einigen anderen Sprachen sind Sequenzen mit so etwas wie
map
odercollect
eingebaut, und niemand muss alle Rahmen sehen, die der Compiler durchlaufen muss, damit sie reibungslos funktionieren. In Scala ist alles in einer Bibliothek und daher im Freien.Tatsächlich ist die Funktionalität
map
, die durch seinen komplizierten Typ unterstützt wird, ziemlich fortgeschritten. Bedenken Sie:Sehen Sie, wie Sie immer den bestmöglichen Typ erhalten? Wenn Sie
Int
s aufInt
s abbilden , erhalten Sie erneut aBitSet
, aber wenn SieInt
s aufString
s abbilden , erhalten Sie einen GeneralSet
. Sowohl der statische Typ als auch die Laufzeitdarstellung des Kartenergebnisses hängen vom Ergebnistyp der Funktion ab, die an das Ergebnis übergeben wird. Und das funktioniert auch, wenn das Set leer ist, so dass die Funktion nie angewendet wird! Soweit ich weiß, gibt es kein anderes Sammlungsframework mit einer entsprechenden Funktionalität. Aus Anwendersicht sollen die Dinge jedoch so funktionieren.Das Problem, das wir haben, ist, dass all die clevere Technologie, die dies ermöglicht, in die Typensignaturen eindringt, die groß und beängstigend werden. Aber vielleicht sollte einem Benutzer nicht standardmäßig die vollständige Typensignatur von angezeigt werden
map
? Wie wäre es, wenn sie aufblicktemap
inBitSet
sie bekam:Die Dokumente würden in diesem Fall nicht lügen, da aus Anwendersicht tatsächlich map den Typ hat
(Int => Int) => BitSet
. Hat abermap
auch einen allgemeineren Typ, der durch Klicken auf einen anderen Link überprüft werden kann.Wir haben solche Funktionen noch nicht in unsere Tools implementiert. Aber ich glaube, wir müssen dies tun, um die Leute nicht abzuschrecken und nützlichere Informationen zu geben. Mit solchen Tools werden hoffentlich intelligente Frameworks und Bibliotheken nicht zu Selbstmordnotizen.
quelle
Ich habe weder einen Doktortitel noch einen anderen Abschluss, weder in CS noch in Mathematik noch in einem anderen Bereich. Ich habe keine Vorkenntnisse mit Scala oder einer ähnlichen Sprache. Ich habe keine Erfahrung mit Systemen, die auch nur aus der Ferne vergleichbar sind. In der Tat, die einzige Sprache , die ich mehr als nur eine oberflächliche Kenntnis von der selbst hat eine Art System ist Pascal, nicht gerade für sein hoch entwickelten Typ - System bekannt. (Es gibt zwar Bereichstypen, die AFAIK so gut wie keine andere Sprache hat, aber das ist hier nicht wirklich relevant.) Die anderen drei Sprachen, die ich kenne, sind BASIC, Smalltalk und Ruby, von denen keine sogar ein Typensystem hat.
Und dennoch habe ich keinerlei Probleme, die Signatur der von
map
Ihnen geposteten Funktion zu verstehen . Es sieht für mich so ziemlich nach der gleichen Signatur aus,map
die ich in jeder anderen Sprache gesehen habe. Der Unterschied ist, dass diese Version allgemeiner ist. Es sieht eher nach einer C ++ STL-Sache aus als beispielsweise nach Haskell. Insbesondere wird vom konkreten Auflistungstyp abstrahiert, indem nur das Argument verlangt wirdIterableLike
, und vom konkreten Rückgabetyp wird abstrahiert, indem nur eine implizite Konvertierungsfunktion benötigt wird, die etwas aus dieser Sammlung von Ergebniswerten aufbauen kann . Ja, das ist ziemlich komplex, aber es ist wirklich nur ein Ausdruck des allgemeinen Paradigmas der generischen Programmierung: Nehmen Sie nichts an, was Sie eigentlich nicht müssen.In diesem Fall muss die Sammlung
map
nicht unbedingt eine Liste sein oder bestellt oder sortierbar sein oder ähnliches. Das einzige, wasmap
wichtig ist, ist, dass es nacheinander auf alle Elemente der Sammlung zugreifen kann, jedoch in keiner bestimmten Reihenfolge. Und es muss nicht wissen, was die resultierende Sammlung ist, es muss nur wissen, wie man sie erstellt. Das ist es also, was seine Typensignatur erfordert.Also statt
Dies ist die traditionelle Typensignatur, für die
map
keine konkreteList
, sondern nur eineIterableLike
Datenstruktur erforderlich istDies wird dann weiter verallgemeinert, indem nur eine Funktion benötigt wird, die das Ergebnis in die vom Benutzer gewünschte Datenstruktur konvertieren kann :
Ich gebe zu, dass die Syntax etwas klobiger ist, aber die Semantik ist dieselbe. Grundsätzlich geht es von
Das ist die traditionelle Signatur für
map
. (Beachten Sie, dass der Eingabelistenparameter aufgrund der objektorientierten Natur von Scala verschwindet, da er nun der implizite Empfängerparameter ist, den jede Methode in einem OO-System mit einem Versand hat.) Dann wurde er von einem konkretenList
zu einem allgemeineren verallgemeinertIterableLike
Jetzt ersetzt es die
IterableLike
Ergebnissammlung durch eine Funktion, die wirklich fast alles erzeugt.Was ich wirklich glaube, ist nicht so schwer zu verstehen. Es gibt wirklich nur ein paar intellektuelle Werkzeuge, die Sie benötigen:
map
ist. Wenn Sie nur die Typensignatur ohne den Namen der Methode angeben würden, wäre es viel schwieriger herauszufinden, was los ist. Da Sie jedoch bereits wissen, wasmap
zu tun ist, und wissen, wie die Typensignatur lauten soll, können Sie die Signatur schnell scannen und sich auf die Anomalien konzentrieren, z. B. "Warum werdenmap
zwei Funktionen als Argumente verwendet, nicht eine?"Keiner dieser drei sollte einem professionellen oder sogar Hobby-Programmierer ernsthafte Kopfschmerzen bereiten.
map
war eine Standardfunktion in so ziemlich jeder Sprache, die in den letzten 50 Jahren entwickelt wurde. Die Tatsache, dass verschiedene Sprachen unterschiedliche Syntax haben, sollte für jeden offensichtlich sein, der eine Website mit HTML und CSS entworfen hat und Sie können nicht einmal eine Remote-Programmierung abonnieren verwandte Mailingliste ohne einen nervigen C ++ - Fanboy aus der Kirche St. Stepanov, der die Vorzüge der generischen Programmierung erklärt.Ja, Scala ist komplex. Ja, Scala verfügt über eines der fortschrittlichsten Systeme, die dem Menschen bekannt sind und mit Sprachen wie Haskell, Miranda, Clean oder Cyclone konkurrieren und diese sogar übertreffen. Aber wenn Komplexität ein Argument gegen den Erfolg einer Programmiersprache wäre, wäre C ++ längst gestorben und wir würden alle Scheme schreiben. Es gibt viele Gründe, warum Scala höchstwahrscheinlich nicht erfolgreich sein wird, aber die Tatsache, dass Programmierer sich nicht die Mühe machen können, ihr Gehirn einzuschalten, bevor sie sich vor die Tastatur setzen, wird wahrscheinlich nicht der Hauptgrund sein.
quelle
That
darauf geschlossen und mit dem Typ verknüpft,B
ist eine Frage, die mir in den Sinn kommt. Woher kommen die Implikationen, wenn man ein anderer ist? Auch ohne diese detaillierten Beobachtungen bin ich persönlich der Meinung, dass dies eine komplexe Signatur ist. Aber offensichtlich gibt es Leute wie Sie da draußen, die davon überhaupt nicht beeindruckt sind!Gleiches in C ++ :
quelle
func
sollte ein Template - Parameter sein, und Sie sollten verwendenresult_of
undis_callable
die anderen Typen und beschränken die Überlastung Set passend :-) zu erhaltenNun, ich kann Ihren Schmerz verstehen, aber ehrlich gesagt sind Leute wie Sie und ich - oder so ziemlich jeder normale Stack Overflow-Benutzer - nicht die Regel.
Was ich damit meine ist, dass ... die meisten Programmierer sich nicht für diese Typensignatur interessieren, weil sie sie nie sehen werden ! Sie lesen keine Dokumentation.
Solange sie ein Beispiel für die Funktionsweise des Codes gesehen haben und der Code sie nicht daran hindert, das erwartete Ergebnis zu erzielen , werden sie sich die Dokumentation niemals ansehen. Wenn dies fehlschlägt, sehen sie sich die Dokumentation an und erwarten oben Anwendungsbeispiele .
In Anbetracht dieser Dinge denke ich, dass:
Jeder (wie bei den meisten Menschen), der jemals auf diese Typensignatur stößt, wird Scala bis zum Äußersten verspotten, wenn er dagegen ist, und sie als Symbol für Scalas Macht betrachten, wenn er Scala mag.
Wenn die Dokumentation nicht erweitert wird, um Verwendungsbeispiele bereitzustellen und klar zu erklären, wozu eine Methode dient und wie sie verwendet wird, kann dies die Einführung von Scala etwas beeinträchtigen.
Auf lange Sicht wird es keine Rolle spielen. Diese Scala kann Dinge tun wie die Bibliotheken für die Scala viel leistungsfähiger und sicherer in der Anwendung geschrieben machen. Diese Bibliotheken und Frameworks werden Programmierer anziehen, die sich für leistungsstarke Tools interessieren.
Programmierer, die Einfachheit und Direktheit mögen, werden weiterhin PHP oder ähnliche Sprachen verwenden.
Leider sind Java-Programmierer sehr an Elektrowerkzeugen interessiert. Als Antwort darauf habe ich gerade meine Erwartung einer allgemeinen Einführung von Scala revidiert. Ich habe überhaupt keinen Zweifel daran, dass Scala eine Mainstream-Sprache werden wird. Nicht C-Mainstream, sondern vielleicht Perl-Mainstream oder PHP-Mainstream.
Apropos Java, haben Sie jemals den Klassenlader ersetzt? Haben Sie jemals untersucht, worum es geht? Java kann beängstigend sein, wenn man sich die Orte ansieht, an denen Framework-Autoren arbeiten. Es ist nur so, dass die meisten Leute es nicht tun. Das Gleiche gilt für Scala, IMHO, aber Early Adopters neigen dazu, unter jeden Felsen zu schauen, auf den sie stoßen, um zu sehen, ob sich dort etwas versteckt.
quelle
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.
Traurig aber wahr.Ja, aber es verhindert auch, dass Menschen abgeschreckt werden. Ich habe das Fehlen von Sammlungen, in denen höherwertige Typen verwendet werden, als große Schwäche angesehen, seit Scala Unterstützung für höherwertige Typen erhalten hat. Dies macht die API-Dokumente komplizierter, macht die Verwendung jedoch natürlicher.
Einige werden es wahrscheinlich tun. Ich denke nicht, dass Scala vielen "professionellen" Entwicklern zugänglich ist, teilweise aufgrund der Komplexität von Scala und teilweise aufgrund der mangelnden Lernbereitschaft vieler Entwickler. Die CTOs, die solche Entwickler beschäftigen, werden zu Recht abgeschreckt sein.
Absolut. Dadurch passen Sammlungen viel besser zum Rest der Sprache und zum Typensystem, auch wenn sie noch einige Ecken und Kanten aufweisen.
Ich benutze es nicht kommerziell. Ich werde wahrscheinlich warten, bis mindestens ein paar Umdrehungen in der 2.8.x-Serie sind, bevor ich überhaupt versuche, sie einzuführen, damit die Fehler beseitigt werden können. Ich werde auch abwarten, wie viel Erfolg EPFL bei der Verbesserung seiner Entwicklungs- und Release-Prozesse hat. Was ich sehe, sieht hoffnungsvoll aus, aber ich arbeite für ein konservatives Unternehmen.
Eines der allgemeineren Themen von "Ist Scala für Mainstream-Entwickler zu kompliziert?" ...
Die meisten Mainstream- oder sonstigen Entwickler warten oder erweitern vorhandene Systeme. Dies bedeutet, dass das meiste, was sie verwenden, von Entscheidungen bestimmt wird, die vor langer Zeit getroffen wurden. Es gibt immer noch viele Leute, die COBOL schreiben.
Der Mainstream-Entwickler von morgen wird daran arbeiten, die heute erstellten Anwendungen zu warten und zu erweitern. Viele dieser Anwendungen werden nicht von Mainstream-Entwicklern erstellt. Die Mainstream-Entwickler von morgen werden die Sprache verwenden, die von den erfolgreichsten Entwicklern neuer Anwendungen von heute verwendet wird.
quelle
Eine Möglichkeit, wie die Scala-Community dazu beitragen kann, die Angst vor Programmierern, die neu in Scala sind, zu lindern, besteht darin, sich auf das Üben zu konzentrieren und anhand von Beispielen zu lehren - viele Beispiele, die klein anfangen und allmählich größer werden. Hier sind einige Websites, die diesen Ansatz verfolgen:
Nachdem man einige Zeit auf diesen Websites verbracht hat, stellt man schnell fest, dass Scala und seine Bibliotheken, obwohl sie möglicherweise schwer zu entwerfen und zu implementieren sind, nicht so schwierig zu verwenden sind, insbesondere in den üblichen Fällen.
quelle
Ich habe einen Bachelor-Abschluss von einer billigen "Massenmarkt" -Universität in den USA, also würde ich sagen, dass ich in die Mitte der User Intelligence- (oder zumindest Bildungs-) Skala falle :) Ich habe mich erst seit ein paar Monaten mit Scala beschäftigt und haben an zwei oder drei nicht trivialen Apps gearbeitet.
Besonders jetzt, da IntelliJ ihre feine IDE mit dem meiner Meinung nach derzeit besten Scala-Plugin veröffentlicht hat, ist die Scala-Entwicklung relativ schmerzlos:
Ich finde, ich kann Scala als "Java ohne Semikolons" verwenden, dh ich schreibe ähnlich aussehenden Code wie in Java und profitiere ein wenig von syntaktischer Kürze, wie sie durch Typinferenz gewonnen wird. Wenn ich es überhaupt mache, ist die Ausnahmebehandlung bequemer. Die Klassendefinition ist ohne das Getter / Setter-Boilerplate viel weniger ausführlich.
Hin und wieder schaffe ich es, eine einzelne Zeile zu schreiben, um das Äquivalent mehrerer Java-Zeilen zu erreichen. Gegebenenfalls macht es Spaß, Ketten funktionaler Methoden wie Map, Fold, Collect, Filter usw. zu komponieren und elegant anzusehen.
Nur selten profitiere ich von Scalas leistungsstärkeren Funktionen: Verschlüsse und Teil- (oder Curry-) Funktionen, Mustervergleich ... so etwas.
Als Neuling kämpfe ich weiterhin mit der knappen und idiomatischen Syntax. Methodenaufrufe ohne Parameter benötigen keine Klammern, außer dort, wo sie vorhanden sind. Fälle in der Übereinstimmungsanweisung benötigen einen fetten Pfeil (
=>
), aber es gibt auch Stellen, an denen Sie einen dünnen Pfeil (->
) benötigen . Viele Methoden haben kurze, aber eher kryptische Namen wie/:
oder\:
- ich kann meine Sachen erledigen, wenn ich genug manuelle Seiten umblättere, aber ein Teil meines Codes sieht am Ende wie Perl oder Zeilenrauschen aus. Ironischerweise fehlt eine der beliebtesten syntaktischen Abkürzungen in Aktion: Ich werde immer wieder von der Tatsache gebissen, dassInt
keine++
Methode definiert ist.Dies ist nur meine Meinung: Ich glaube, Scala hat die Leistungsfähigkeit von C ++ in Kombination mit der Komplexität und Lesbarkeit von C ++. Die syntaktische Komplexität der Sprache macht es auch schwierig, die API-Dokumentation zu lesen.
Scala ist in vielerlei Hinsicht sehr gut durchdacht und brillant. Ich vermute, dass viele Akademiker gerne darin programmieren würden. Es ist jedoch auch voller Klugheit und Fallstricke, es hat eine viel höhere Lernkurve als Java und ist schwerer zu lesen. Wenn ich die Foren scanne und sehe, wie viele Entwickler immer noch mit den Feinheiten von Java zu kämpfen haben, kann ich mir nicht vorstellen, dass Scala jemals eine Mainstream-Sprache wird . Kein Unternehmen kann es rechtfertigen, seine Entwickler zu einem dreiwöchigen Scala-Kurs zu schicken, wenn sie früher nur einen einwöchigen Java-Kurs benötigten.
quelle
Ich denke, das Hauptproblem bei dieser Methode ist, dass das
(implicit bf : CanBuildFrom[Repr, B, That])
ohne Erklärung geht. Obwohl ich weiß, was implizite Argumente sind, gibt es keine Hinweise darauf, wie sich dies auf den Aufruf auswirkt. Das Jagen durch den Scaladoc macht mich nur verwirrter (nur wenige der Klassen, die sich darauf beziehenCanBuildFrom
sogar Dokumentation).Ich denke, ein einfaches "es muss ein implizites Objekt im Gültigkeitsbereich geben
bf
, das einen Builder für Objekte vom TypB
in den Rückgabetyp liefertThat
" würde etwas helfen, aber es ist eine Art berauschendes Konzept, wenn alles, was Sie wirklich tun möchten, MapA
's to istB
's. Tatsächlich bin ich mir nicht sicher, ob das richtig ist, da ich nicht weiß, was der TypRepr
und die Dokumentation dafür bedeutenTraversable
gibt mit Sicherheit überhaupt keinen Hinweis.Ich habe also zwei Möglichkeiten, von denen keine angenehm ist:
Ich verstehe, dass Scala im Wesentlichen den Mut aufdeckt, wie diese Dinge funktionieren, und dass dies letztendlich eine Möglichkeit bietet, das zu tun, was oxbow_lakes beschreibt. Aber es ist eine Ablenkung in der Unterschrift.
quelle
Repr
ist die durchquerbare Darstellung, dh.List
oderSet
oderMap
. Ich denke, wenn Sie sich als Framework mit Methodensignaturen befassen möchten (anstatt nur die Methoden durch Kopieren von Beispielen zu verwenden), müssen Sie zuerst das allgemeine Design verstehen. IMHO sollte der Scaladoc voller Beispiele seinRepr
bedeutet? Ich würde eine Erklärung im Scaladoc erwarten, aber es war mir wirklich nicht klar. Ich denke, dies ist ein allgemeines Muster im Scaladoc (sieheActor.react
undActor.receive
- mir wurde gesagt und ich habe gesehen, dass sie völlig unterschiedliche Dinge tun, aber ihr Scaladoc ist identisch).Ich bin ein Scala-Anfänger und sehe ehrlich gesagt kein Problem mit dieser Typensignatur. Der Parameter ist die zuzuordnende Funktion und der implizite Parameter der Builder, um die richtige Auflistung zurückzugeben. Klar und lesbar.
Das Ganze ist eigentlich ziemlich elegant. Mit den Builder-Typparametern kann der Compiler den richtigen Rückgabetyp auswählen, während der implizite Parametermechanismus diesen zusätzlichen Parameter vor dem Klassenbenutzer verbirgt. Ich habe es versucht:
Das ist Polymorphismus, richtig gemacht.
Nun, zugegeben, es ist kein Mainstream-Paradigma und es wird viele abschrecken. Es wird aber auch viele anziehen, die Wert auf Ausdruckskraft und Eleganz legen.
quelle
Leider ist die von Ihnen angegebene Signatur für die Karte falsch und es gibt in der Tat berechtigte Kritik.
Der erste Kritikpunkt ist, dass wir durch das Untergraben der Signatur für die Karte etwas allgemeineres haben. Es ist ein häufiger Fehler zu glauben, dass dies standardmäßig eine Tugend ist. Ist es nicht. Die Kartenfunktion ist sehr gut definiert als kovarianter Funktor Fx -> (x -> y) -> Fy unter Einhaltung der beiden Gesetze der Zusammensetzung und Identität. Alles andere, was "Karte" zugeschrieben wird, ist eine Travestie.
Die angegebene Signatur ist etwas anderes, aber keine Karte. Was ich vermute, ist eine spezialisierte und leicht veränderte Version der "Traverse" -Signatur aus dem Papier "The Essence of the Iterator Pattern". Hier ist seine Unterschrift:
Ich werde es in Scala umwandeln:
Natürlich scheitert es - es ist nicht allgemein genug! Es ist auch etwas anders (beachten Sie, dass Sie eine Karte erhalten können, indem Sie den Identity-Funktor durchlaufen). Ich vermute jedoch, dass wir diesen Fehler nicht sehen würden, wenn die Autoren der Bibliothek besser über gut dokumentierte Verallgemeinerungen der Bibliothek informiert wären (Applikative Programmierung mit Effekten geht den oben genannten voraus).
Zweitens ist die Kartenfunktion ein Sonderfall in Scala, da sie für das Verständnis verwendet wird. Dies bedeutet leider, dass ein besser ausgestatteter Bibliotheksdesigner diesen Fehler nicht ignorieren kann, ohne auch den syntaktischen Zucker des Verständnisses zu opfern. Mit anderen Worten, wenn die Designer der Scala-Bibliothek eine Methode zerstören sollten, wird dies leicht ignoriert, aber bitte nicht zuordnen!
Ich hoffe, jemand spricht darüber, denn so wie es ist, wird es schwieriger, die Fehler zu umgehen, auf die Scala besteht, anscheinend aus Gründen, gegen die ich starke Einwände habe. Das heißt, die Lösung für "die unverantwortlichen Einwände des durchschnittlichen Programmierers (dh zu hart!)" Ist nicht "sie zu beschwichtigen, um es ihnen leichter zu machen", sondern Hinweise und Unterstützung zu geben, um bessere Programmierer zu werden. Die Ziele von mir und Scala sind in dieser Frage umstritten, aber zurück zu Ihrem Punkt.
Sie haben wahrscheinlich Ihren Standpunkt klargestellt und bestimmte Antworten des "durchschnittlichen Programmierers" vorhergesagt. Das heißt, die Leute, die behaupten werden "aber es ist zu kompliziert!" oder solche. Dies sind die Yegges oder Blochs, auf die Sie sich beziehen. Meine Reaktion auf diese Leute der Anti-Intellektualismus / Pragmatismus-Bewegung ist ziemlich hart und ich erwarte bereits eine Flut von Antworten, also werde ich sie weglassen.
Ich hoffe wirklich, dass sich die Scala-Bibliotheken verbessern oder zumindest die Fehler sicher in einer Ecke versteckt werden können. Java ist eine Sprache, in der "der Versuch, etwas Nützliches zu tun" so unglaublich kostspielig ist, dass es sich oft nicht lohnt, weil die überwältigende Menge an Fehlern einfach nicht vermieden werden kann. Ich flehe Scala an, nicht den gleichen Weg zu gehen.
quelle
Ich stimme sowohl der Frage als auch Martins Antwort voll und ganz zu :). Selbst in Java ist das Lesen von Javadoc mit Generika aufgrund des zusätzlichen Rauschens viel schwieriger als es sein sollte. Dies wird in Scala noch verstärkt, wo implizite Parameter wie im Beispielcode der Fragen verwendet werden (während die impliziten Parameter sehr nützliche Sammlung-Morphing-Aufgaben ausführen).
Ich denke nicht, dass es ein Problem mit der Sprache an sich ist - ich denke, es ist eher ein Werkzeugproblem. Und obwohl ich dem zustimme, was Jörg W Mittag sagt, denke ich, dass ein Blick auf Scaladoc (oder die Dokumentation eines Typs in Ihrer IDE) so wenig Gehirnleistung wie möglich erfordern sollte, um herauszufinden, was eine Methode ist, was sie benötigt und zurückgibt. Es sollte nicht nötig sein, ein bisschen Algebra auf ein Stück Papier zu hacken, um es zu bekommen :)
Sicherlich brauchen IDEs eine gute Möglichkeit, alle Methoden für jede Variable / jeden Ausdruck / Typ anzuzeigen (wie in Martins Beispiel können alle Generika eingefügt sein, so dass es schön und einfach zu groken ist). Ich mag Martins Idee, die Implikationen auch standardmäßig zu verbergen.
Um das Beispiel in scaladoc zu nehmen ...
Wenn ich mir das in scaladoc anschaue, möchte ich, dass der generische Block [B, That] standardmäßig ausgeblendet wird sowie der implizite Parameter (möglicherweise wird angezeigt, wenn Sie mit der Maus über ein kleines Symbol fahren) - als zusätzliches Element zum Groken Lesen, was normalerweise nicht so relevant ist. zB stell dir vor, das sah so aus ...
nett und klar und offensichtlich, was es tut. Sie fragen sich vielleicht, was "Das" ist. Wenn Sie mit der Maus darüber fahren oder darauf klicken, wird möglicherweise der Text [B, Das] erweitert, der beispielsweise das "Das" hervorhebt.
Vielleicht könnte ein kleines Symbol für die [] Deklaration und den (impliziten ...) Block verwendet werden, damit klar ist, dass kleine Teile der Anweisung reduziert sind? Es ist schwer, einen Token dafür zu verwenden, aber ich werde einen verwenden. zur Zeit...
Standardmäßig ist das 'Rauschen' des Typsystems also vor den wichtigsten 80% dessen verborgen, was die Leute betrachten müssen - dem Methodennamen, seinen Parametertypen und seinem Rückgabetyp auf nette, einfache und übersichtliche Weise - mit wenig erweiterbaren Links zum Detail wenn es dich wirklich interessiert.
Die meisten Leute lesen Scaladoc, um herauszufinden, welche Methoden sie für einen Typ aufrufen können und welche Parameter sie übergeben können. Wir überladen Benutzer mit viel zu vielen Details, wie IMHO.
Hier ist ein weiteres Beispiel ...
Wenn wir nun die Generika-Deklaration versteckt haben, ist sie leichter zu lesen
Wenn die Leute dann beispielsweise über A1 schweben, könnten wir die Deklaration von A1 als A1 <: A zeigen. Kovariante und kontravariante Typen in Generika fügen ebenfalls viel Rauschen hinzu, das für Benutzer, wie ich denke, viel einfacher zu verstehen ist.
quelle
Ich weiß nicht, wie ich es Ihnen sagen soll, aber ich habe einen Doktortitel aus Cambridge und verwende 2.8 ganz gut.
Im Ernst, ich habe kaum Zeit mit 2.7 verbracht (es funktioniert nicht mit einer Java-Bibliothek, die ich verwende) und habe vor etwas mehr als einem Monat angefangen, Scala zu verwenden. Ich habe einige Erfahrungen mit Haskell (nicht viel), habe aber die Dinge, über die Sie sich Sorgen machen, einfach ignoriert und nach Methoden gesucht, die meinen Erfahrungen mit Java entsprechen (die ich beruflich verwende).
Also: Ich bin ein "neuer Benutzer" und habe mich nicht abschrecken lassen - die Tatsache, dass es wie Java funktioniert, gab mir genug Selbstvertrauen, um die Teile zu ignorieren, die ich nicht verstand.
(Der Grund, warum ich mich mit Scala befasst habe, war zum Teil, dass ich es bei der Arbeit vorantreiben sollte, und ich werde es noch nicht tun. Die Dokumentation weniger einschüchternd zu machen, würde sicherlich helfen, aber was mich überrascht hat, ist, wie viel es noch ist Ändern und weiterentwickelt werden (um fair zu sein, was mich am meisten überraschte, war, wie großartig es ist, aber die Änderungen kamen nur an zweiter Stelle). Ich denke also, ich würde es vorziehen, wenn die begrenzten Ressourcen dafür eingesetzt würden ein Endzustand - ich glaube nicht, dass sie erwartet hatten, so bald so beliebt zu sein.)
quelle
Ich kenne Scala überhaupt nicht, aber vor ein paar Wochen konnte ich Clojure nicht lesen. Jetzt kann ich das meiste davon lesen, aber noch nichts über die einfachsten Beispiele hinaus schreiben . Ich vermute, Scala ist nicht anders. Sie benötigen ein gutes Buch oder einen guten Kurs, je nachdem, wie Sie lernen. Wenn ich nur die obige Kartenerklärung lese , habe ich vielleicht 1/3 davon.
Ich glaube, die größeren Probleme sind nicht die Syntax dieser Sprachen, sondern die Übernahme und Internalisierung der Paradigmen , die sie im alltäglichen Produktionscode verwendbar machen. Für mich war Java kein großer Sprung von C ++, was kein großer Sprung von C war, was überhaupt kein Sprung von Pascal war, noch Basic usw. Aber das Codieren in einer funktionalen Sprache wie Clojure ist ein großer Sprung (für ich sowieso). Ich denke, in Scala können Sie im Java-Stil oder im Scala-Stil codieren. Aber in Clojure werden Sie ein ziemliches Durcheinander schaffen, wenn Sie versuchen, Ihre zwingenden Gewohnheiten von Java fernzuhalten.
quelle
Scala hat viele verrückte Funktionen (insbesondere wenn es um implizite Parameter geht), die sehr kompliziert und akademisch aussehen, aber die Bedienung vereinfachen sollen. Die nützlichsten erhalten syntaktischen Zucker (
[A <% B]
was bedeutet, dass ein Objekt vom Typ A eine implizite Umwandlung in ein Objekt vom Typ B hat) und eine gut dokumentierte Erklärung dessen, was sie tun. In den meisten Fällen können Sie als Client dieser Bibliotheken die impliziten Parameter ignorieren und darauf vertrauen, dass sie das Richtige tun.quelle
Ich denke nicht, dass dies der Hauptfaktor ist, der die Popularität von Scala beeinflussen wird, da Scala viel Leistung besitzt und seine Syntax einem Java / C ++ / PHP-Programmierer nicht so fremd ist wie Haskell, OCaml, SML, Lisps, usw..
Aber ich denke, Scalas Popularität wird weniger als heute ein Plateau erreichen, da ich denke, dass die nächste Mainstream-Sprache stark vereinfacht werden muss und der einzige Weg, den ich sehe, um dorthin zu gelangen, reine Unveränderlichkeit ist, dh deklarativ wie HTML, aber Turing vollständig . Ich bin jedoch voreingenommen, weil ich eine solche Sprache entwickle, aber ich habe dies erst getan, nachdem ich über ein mehrmonatiges Studium ausgeschlossen hatte, dass Scala nicht für das ausreichen konnte, was ich brauchte.
Ich glaube nicht, dass Scalas Ruf unter dem Haskell-Komplex leiden wird. Aber ich denke, dass einige das Lernen aufschieben werden, weil ich für die meisten Programmierer noch keinen Anwendungsfall sehe, der sie zwingt, Scala zu verwenden, und sie werden das Lernen darüber hinauszögern. Vielleicht ist die hochskalierbare Serverseite der überzeugendste Anwendungsfall.
Und für den Mainstream-Markt ist das erste Erlernen von Scala kein "Hauch frischer Luft", bei dem man sofort Programme schreibt, beispielsweise zuerst HTML oder Python. Scala neigt dazu, auf dir zu wachsen, nachdem man alle Details gelernt hat, über die man von Anfang an stolpert. Wenn ich jedoch von Anfang an Programmieren in Scala gelesen hätte, wären meine Erfahrungen und meine Meinung zur Lernkurve anders gewesen.
Bestimmt.
Ich benutze Scala als erste Plattform für meine neue Sprache. Ich würde wahrscheinlich keinen Code in Scalas Sammlungsbibliothek erstellen, wenn ich Scala anderweitig kommerziell verwenden würde. Ich würde meine eigene kategorietheoretische Bibliothek erstellen, da ich beim ersten Mal Scalaz 'Typensignaturen noch ausführlicher und unhandlicher fand als Scalas Sammlungsbibliothek. Ein Teil dieses Problems ist vielleicht Scalas Art, Typklassen zu implementieren, und das ist ein kleiner Grund, warum ich meine eigene Sprache erstelle.
Ich habe mich entschlossen, diese Antwort zu schreiben, weil ich mich zwingen wollte, Scalas Sammlungsklassendesign zu recherchieren und mit dem zu vergleichen, das ich für meine Sprache mache. Könnte auch meinen Denkprozess teilen.
Die Verwendung einer Builder-Abstraktion in den 2.8 Scala-Sammlungen ist ein solides Designprinzip. Ich möchte im Folgenden zwei Design-Kompromisse untersuchen.
NUR SCHREIBCODE: Nachdem ich diesen Abschnitt geschrieben habe, habe ich den Kommentar von Carl Smotricz gelesen der mit dem übereinstimmt, was ich als Kompromiss erwarte. Die Kommentare von James Strachan und davetron5000 stimmen darin überein, dass die Bedeutung von That (es ist nicht einmal That [B]) und der Mechanismus des Impliziten nicht leicht intuitiv zu erfassen sind. Siehe meine Verwendung von Monoid in Ausgabe 2 unten, die meiner Meinung nach viel expliziter ist. In Derek Mahar's Kommentar geht es darum, Scala zu schreiben, aber was ist mit dem Lesen der Scala anderer, was nicht "in den üblichen Fällen" ist.
Eine Kritik, die ich über Scala gelesen habe, ist, dass es einfacher ist, sie zu schreiben, als den Code zu lesen, den andere geschrieben haben. Und ich finde, dass dies gelegentlich aus verschiedenen Gründen zutrifft (z. B. viele Möglichkeiten, eine Funktion zu schreiben, automatische Schließungen, Einheit für DSLs usw.), aber ich bin unentschlossen, ob dies ein wichtiger Faktor ist. Hier hat die Verwendung impliziter Funktionsparameter Vor- und Nachteile. Auf der positiven Seite reduziert es die Ausführlichkeit und automatisiert die Auswahl des Builder-Objekts. Bei Odersky BeispielDie Konvertierung von einem BitSet, dh Set [Int], in ein Set [String] ist implizit. Der unbekannte Leser des Codes weiß möglicherweise nicht ohne weiteres, um welche Art von Sammlung es sich handelt, es sei denn, er kann gut über alle potenziellen unsichtbaren impliziten Builder-Kandidaten nachdenken, die im aktuellen Paketumfang vorhanden sein könnten. Natürlich wissen der erfahrene Programmierer und der Verfasser des Codes, dass BitSet auf Int beschränkt ist, daher muss eine Zuordnung zu String in einen anderen Sammlungstyp konvertiert werden. Aber welcher Sammlungstyp? Es ist nicht explizit angegeben.
AD-HOC-SAMMLUNGSDESIGN: Nachdem ich diesen Abschnitt geschrieben hatte, las ich Tony Morris 'Kommentar und stellte fest, dass ich fast den gleichen Punkt mache. Vielleicht wird meine ausführlichere Darstellung den Punkt klarer machen.
In "Fighting Bit Rot with Types" von Odersky & Moors werden zwei Anwendungsfälle vorgestellt. Sie sind die Beschränkung von BitSet auf Int-Elemente und Map to Pair Tuple-Elemente und werden als Grund dafür angegeben, dass die allgemeine Elementzuordnungsfunktion A => B in der Lage sein muss, alternative Zielsammlungstypen zu erstellen. Afaik ist dies jedoch aus kategorietheoretischer Sicht fehlerhaft. Um in der Kategorietheorie konsistent zu sein und somit Eckfälle zu vermeiden, sind diese Sammlungstypen Funktoren, bei denen jeder Morphismus, A => B, zwischen Objekten in derselben Funktorkategorie, Liste [A] => Liste [B], BitSet, zugeordnet werden muss [A] => BitSet [B]. Eine Option ist beispielsweise ein Funktor, der als Sammlung von Mengen aus einem Some (Objekt) und dem None angesehen werden kann. Es gibt keine allgemeine Karte von Option's None oder List's Nil zu anderen Funktoren, die dies nicht tun.
Hier wird eine Kompromissentscheidung getroffen. In der Design for Collections-Bibliothek meiner neuen Sprache habe ich beschlossen, alles zu einem Funktor zu machen. Wenn ich also ein BitSet implementiere, muss es alle Elementtypen unterstützen, indem eine interne Darstellung ohne Bitfeld verwendet wird, wenn eine Nicht-Bit-Darstellung angezeigt wird Parameter vom Typ Integer, und diese Funktionalität befindet sich bereits in der Menge, von der sie in Scala erbt. Und Map in meinem Design muss nur seine Werte zuordnen, und es kann eine separate Nicht-Funktor-Methode zum Zuordnen seiner (Schlüssel-, Wert-) Paartupel bereitstellen. Ein Vorteil ist, dass jeder Funktor dann meist auch ein Applikativ und vielleicht auch eine Monade ist. Somit werden alle Funktionen zwischen Elementtypen, z. B. A => B => C => D => ..., automatisch auf die Funktionen zwischen angehobenen Anwendungstypen aufgehoben, z. B. Liste [A] => Liste [B] => Liste [ C] => Liste [D] => .... Für die Zuordnung von einem Funktor zu einer anderen Sammlungsklasse biete ich eine Kartenüberladung an, die ein Monoid akzeptiert, z. B. Nil, None, 0, "", Array () usw. Die Builder-Abstraktionsfunktion ist also die Append-Methode eines Monoids und wird explizit als notwendiger Eingabeparameter angegeben, also ohne unsichtbare implizite Konvertierungen. (Tangente: Dieser Eingabeparameter ermöglicht auch das Anhängen an nicht leere Monoide, was Scalas Kartendesign nicht kann.) Solche Konvertierungen sind eine Karte und eine Falte im selben Iterationsdurchlauf. Außerdem biete ich eine durchlaufbare im Sinne der Kategorie "Applikative Programmierung mit Effekten" von McBride & Patterson an, die auch Map + Fold in einem einzigen Iterationsdurchlauf von jeder Durchquerung zu jeder Anwendung ermöglicht, wobei fast jede Sammlungsklasse beides ist.
Die Scala-Sammlungen sind also "ad-hoc" in dem Sinne, dass sie nicht auf Kategorietheorie beruhen, und Kategorietheorie ist die Essenz der Denotationssemantik auf höherer Ebene. Obwohl die impliziten Builder von Scala auf den ersten Blick "allgemeiner" erscheinen als ein Funktormodell + Monoid-Builder + Traversable -> anwendbar, sind sie afaik nachweislich nicht mit einer Kategorie konsistent, und daher wissen wir nicht, welchen Regeln sie in der Der allgemeinste Sinn und die Eckfälle werden möglicherweise keinem Kategoriemodell gehorchen. Es ist einfach nicht wahr, dass das Hinzufügen weiterer Variablen etwas allgemeineres macht, und dies war einer der großen Vorteile der Kategorietheorie, da sie Regeln bereitstellt, nach denen die Allgemeinheit beibehalten und gleichzeitig zur Semantik auf höherer Ebene übergegangen werden kann. Eine Sammlung ist eine Kategorie.
Ich habe irgendwo gelesen, ich denke, es war Odersky, als eine weitere Rechtfertigung für das Bibliotheksdesign, dass das Programmieren in einem rein funktionalen Stil die Kosten einer begrenzten Rekursion und Geschwindigkeit verursacht, wenn keine Schwanzrekursion verwendet wird. Ich habe es nicht schwierig gefunden, in jedem Fall, auf den ich bisher gestoßen bin, eine Schwanzrekursion anzuwenden.
Außerdem habe ich die unvollständige Vorstellung, dass einige der Kompromisse von Scala darauf zurückzuführen sind, dass ich versucht habe, sowohl eine veränderliche als auch eine unveränderliche Sprache zu sein, im Gegensatz zu beispielsweise Haskell oder der Sprache, die ich entwickle. Dies stimmt mit Tony Morris 'Kommentar zum Verständnis überein. In meiner Sprache gibt es keine Schleifen und keine veränderlichen Konstrukte. Meine Sprache wird (vorerst) auf Scala sitzen und hat viel zu verdanken, und dies wäre nicht möglich, wenn Scala nicht das allgemeine Typensystem und die Veränderlichkeit hätte. Das mag jedoch nicht zutreffen, da ich denke, dass Odersky & Moors ("Fighting Bit Rot with Types") falsch ist, um zu behaupten, dass Scala die einzige OOP-Sprache mit höheren Arten ist, weil ich (selbst und über Bob Harper) diesen Standard verifiziert habe ML hat sie. Es scheint auch, dass das SML-Typensystem (seit den 1980er Jahren) gleichermaßen flexibel sein kann. Dies kann nicht ohne weiteres erkannt werden, da die Syntax Java (und C ++ / PHP) nicht so sehr ähnelt wie Scala. Auf jeden Fall ist dies keine Kritik an Scala, sondern ein Versuch, eine unvollständige Analyse der Kompromisse vorzulegen, was meiner Meinung nach für die Frage von Belang ist. Scala und SML leiden nicht unter Haskells UnfähigkeitDiamant-Mehrfachvererbung , was kritisch ist und ich verstehe, ist, warum so viele Funktionen im Haskell-Präludium für verschiedene Typen wiederholt werden.
quelle
Es scheint notwendig, hier einen Abschluss anzugeben: BA in Politikwissenschaft und B.ed in Informatik.
Auf den Punkt:
Scala ist schwierig, weil das zugrunde liegende Programmierparadigma schwierig ist. Funktionale Programmierung macht vielen Menschen Angst. Es ist möglich, Schließungen in PHP zu erstellen, aber die Leute tun dies selten. Also nein, nicht diese Unterschrift, sondern alles andere wird die Menschen abschrecken, wenn sie nicht über die spezifische Ausbildung verfügen, um die Macht des zugrunde liegenden Paradigmas wertzuschätzen.
Wenn diese Ausbildung verfügbar ist, kann es jeder tun. Letztes Jahr habe ich mit ein paar Schulkindern in SCALA einen Schachcomputer gebaut! Sie hatten ihre Probleme, aber am Ende haben sie es gut gemacht.
Ich würde mir keine Sorgen machen.
quelle
Ich habe auch einen Mathematik-Abschluss in Oxford! Ich habe eine Weile gebraucht, um die neuen Kollektionen zu bekommen. Aber ich mag es jetzt sehr, wo ich es tue. Tatsächlich war die Eingabe von 'map' eines der ersten großen Dinge, die mich in 2.7 nervten (vielleicht seit ich als erstes eine der Sammlungsklassen untergeordnet habe).
Das Lesen von Martins Artikel über die neuen 2.8-Sammlungen hat wirklich dazu beigetragen, die Verwendung von Implicits zu erklären, aber ja, die Dokumentation selbst muss definitiv die Rolle verschiedener Arten von Implicits in Methodensignaturen von Kern-APIs besser erklären.
Mein Hauptanliegen ist eher Folgendes: Wann wird 2.8 veröffentlicht? Wann werden die Fehlerberichte nicht mehr eingehen? Hat das Scala-Team mehr abgebissen, als es mit 2.8 kauen kann / versucht, zu viel auf einmal zu ändern?
Ich würde wirklich gerne sehen, dass 2.8 für die Veröffentlichung als Priorität stabilisiert wird, bevor überhaupt etwas Neues hinzugefügt wird, und mich fragen (während ich von der Seitenlinie aus schaue), ob einige Verbesserungen an der Art und Weise vorgenommen werden könnten, wie die Entwicklungs-Roadmap für den Scala-Compiler verwaltet wird.
quelle
Was ist mit Fehlermeldungen auf der verwendeten Website?
Und wann kommt der Anwendungsfall, bei dem vorhandene Typen in einen benutzerdefinierten Typ integriert werden müssen, der zu einem DSL passt? Man muss in Fragen der Assoziation, des Vorrangs, impliziter Konvertierungen, impliziter Parameter, höherer Arten und möglicherweise existenzieller Typen gut ausgebildet sein.
Es ist sehr gut zu wissen, dass es meistens einfach ist, aber es ist nicht unbedingt genug. Zumindest muss es einen geben, der dieses Zeug kennt, wenn eine weit verbreitete Bibliothek entworfen werden soll.
quelle