Julia: Überprüfung der API-Konsistenz

Erstellt am 2. Feb. 2017  ·  131Kommentare  ·  Quelle: JuliaLang/julia

Ich beginne dies als einen Ort, an dem Sie Notizen zu Dingen hinterlassen können, die Sie bei der Überprüfung der API-Konsistenz in Julia 1.0 berücksichtigen sollten.

  • [x] Priorisierung des Übereinkommens. Auflisten und Priorisieren unserer Was-kommt-zuerst-Konventionen in Bezug auf Funktionsargumente für Do-Blöcke, E / A-Argumente für gedruckte Funktionen, Ausgaben für In-Place-Funktionen usw. (https://github.com/JuliaLang/julia/issues/ 19150).

  • [] Positions- und Schlüsselwortargumente. Vor langer Zeit hatten wir keine Keyword-Argumente. Sie werden aus Leistungsgründen immer noch manchmal vermieden. Wir sollten diese Auswahl auf der Grundlage der besten API treffen, nicht auf der Grundlage dieser Art von historischem Gepäck (Keyword-Leistungsprobleme sollten ebenfalls behoben werden, damit dies nicht länger berücksichtigt wird).

  • [] Metaprogrammierwerkzeuge. Wir haben viele Tools wie @code_xxx , die mit zugrunde liegenden Funktionen wie code_xxx gepaart sind. Diese sollten sich konsistent verhalten: Ähnliche Signaturen Wenn Funktionen mit ähnlichen Signaturen vorhanden sind, stellen Sie sicher, dass sie ähnliche Makroversionen haben. Im Idealfall sollten alle Werte zurückgeben, anstatt einige Werte zurückzugeben und andere Druckergebnisse, obwohl dies für Dinge wie LLVM-Code und Assembly-Code schwierig sein kann.

  • [] IO <=> Dateinamenäquivalenz. Im Allgemeinen erlauben wir, Dateinamen als Zeichenfolgen anstelle von E / A-Objekten zu übergeben. Das Standardverhalten besteht darin, die Datei im entsprechenden Modus zu öffnen, das resultierende E / A-Objekt mit denselben Argumenten an dieselbe Funktion zu übergeben und dann sicherzustellen, dass das E / A-Objekt vorhanden ist wird danach geschlossen. Stellen Sie sicher, dass alle geeigneten E / A-akzeptierenden Funktionen diesem Muster folgen.

  • [] Reduziert APIs. Stellen Sie sicher, dass die Reduzierungen ein konsistentes Verhalten aufweisen. Alle nehmen vor der Reduktion eine Kartenfunktion an. kongruente Dimensionsargumente usw.

  • [] Dimensionsargumente. Konsistente Behandlung der Eingabeargumente "Über diese [diese] Dimension [s] berechnen", welche Typen zulässig sind usw. Überlegen Sie, ob dies als Schlüsselwortargumente gewünscht wird.

  • [] Mutierende / nicht mutierende Paare. Überprüfen Sie, ob nicht mutierende Funktionen mit mutierenden Funktionen gepaart sind, wo dies sinnvoll ist, und umgekehrt.

  • [] Tupel gegen Vararg. Überprüfen Sie, ob eine allgemeine Übereinstimmung zwischen der Verwendung eines Tupels als letztes Argument oder eines Vararg besteht.

  • [] Gewerkschaften vs. Nullables vs. Fehler. Konsistente Regeln, wann Funktionen Fehler auslösen sollen und wann sie Nullables oder Unions zurückgeben sollen (z. B. parse / tryparse, match usw.).

  • [] Generatoren so weit wie möglich unterstützen. Stellen Sie sicher, dass alle Funktionen, die mit Generatoren sinnvoll funktionieren könnten, dies tun. Wir sind schon ziemlich gut darin, aber ich schätze, wir haben ein paar verpasst.

  • [] Auswahl des Ausgabetyps. Seien Sie konsistent darüber, ob APIs vom Typ "Ausgabetyp" in Bezug auf den Elementtyp oder den Gesamtcontainertyp sein sollen (Ref. Nr. 11557 und Nr. 16740).

  • [x] Wähle einen Namen. Es gibt einige Funktionen / Operatoren mit Aliasnamen. Ich denke, dies ist in Fällen in Ordnung, in denen einer der Namen nicht ASCII ist und die ASCII-Version bereitgestellt wird, damit die Benutzer weiterhin reinen ASCII-Code schreiben können, aber es gibt auch Fälle wie <: denen es sich um einen Alias ​​für issubtype wobei beide Namen ASCII sind. Wir sollten einen auswählen und den anderen ablehnen. Wir haben is zugunsten von === abgelehnt und sollten hier ähnlich vorgehen.

  • [] Konsistenz mit DataStructures . Es geht etwas über den Rahmen von Base Julia hinaus, aber wir sollten sicherstellen, dass alle Sammlungen in DataStructures konsistente APIs mit denen von Base haben. Die Verbindung in die andere Richtung besteht darin, dass einige dieser Typen möglicherweise darüber informieren, wie wir die APIs in Base entwerfen, da wir möchten, dass sie reibungslos und konsistent erweitert werden.

  • [] NaNs vs. DomainErrors. Siehe https://github.com/JuliaLang/julia/issues/5234 - haben Sie eine Richtlinie, wann was zu tun ist, und stellen Sie sicher, dass diese konsequent befolgt wird.

  • [] Sammlungsgenerator <=>. Manchmal möchten Sie eine Sammlung, manchmal möchten Sie einen Generator. Wir sollten alle unsere APIs durchgehen und sicherstellen, dass es für beide eine Option gibt, wo dies sinnvoll ist. Es war einmal eine Konvention, einen Großbuchstaben für die Generatorversion und einen Kleinbuchstaben für die Version zu verwenden, die eifrig ist und eine neue Sammlung zurückgibt. Aber niemand hat jemals darauf geachtet, also brauchen wir vielleicht eine neue Konvention.

  • [] Funktionen höherer Ordnung für Mitarbeiter. Derzeit durchlaufen einige Funktionen höherer Ordnung assoziative Sammlungen mit der Signatur (k,v) - z. B. map , filter . Andere iterieren über Paare, dh mit der Signatur kv , wobei der Körper das Paar explizit in k und v - z. B. all , any . Dies sollte überprüft und konsistent gemacht werden.

  • [x] Konvertieren vs. Konstruieren. Konvertierung gegebenenfalls zulassen. ZB gab es mehrere Probleme / Fragen zu convert(String, 'x') . Im Allgemeinen ist eine Konvertierung angemessen, wenn es eine einzelne kanonische Transformation gibt. Die Konvertierung von Zeichenfolgen in Zahlen ist im Allgemeinen nicht angemessen, da es viele Möglichkeiten gibt, Zahlen in Textform darzustellen. Daher müssen wir stattdessen mit Optionen analysieren. Es gibt jedoch eine einzige kanonische Möglichkeit, Versionsnummern als Zeichenfolgen darzustellen, sodass wir diese konvertieren können. Wir sollten diese Logik sorgfältig und universell anwenden.

  • [] Überprüfen Sie die Vollständigkeit der Sammlungs-API. Wir sollten uns die Standardbibliotheksfunktionen für Sammlungen ansehen, die von anderen Sprachen bereitgestellt werden, und sicherstellen, dass wir eine Möglichkeit haben, die gemeinsamen Operationen auszudrücken, die sie haben. Zum Beispiel haben wir keine flatten -Funktion oder eine concat -Funktion. Wir sollten es wahrscheinlich tun.

  • [] Unterstreichen Sie die Prüfung.

deprecation

Hilfreichster Kommentar

Unterstreichen Sie die Prüfung

Das Folgende ist eine Analyse aller aus Base exportierten Symbole, die Unterstriche enthalten, nicht veraltet sind und keine Zeichenfolgenmakros sind. Die Hauptsache hier ist, dass dies nur exportierte Namen sind; Dies schließt keine nicht exportierten Namen ein, die wir den Leuten sagen, dass sie qualifiziert anrufen sollen.

Ich habe die Dinge nach Kategorien getrennt. Hoffentlich ist das nützlicher als nervig.

Reflexion

Wir haben folgende Makros mit entsprechenden Funktionen:

  • [] @code_llvm , code_llvm
  • [] @code_lowered , code_lowered
  • [] @code_native , code_native
  • [] @code_typed , code_typed
  • [] @code_warntype , code_warntype

Welche Änderungen auch immer auf die Makros angewendet werden, sollte auf ähnliche Weise auf die Funktionen angewendet werden.

  • [x] module_name -> nameof (# 25622)
  • [x] module_parent -> parentmodule (# 25629, siehe # 25436 für einen früheren Umbenennungsversuch)
  • [x] method_exists -> hasmethod (# 25615)
  • [x] object_id -> objectid (# 25615)
  • [] pointer_from_objref

pointer_from_objref könnte vielleicht einen aussagekräftigeren Namen vertragen, vielleicht so etwas wie address ?

Aliase für C interop

Die Typ-Aliase, die Unterstriche enthalten, sind C_NULL , Cintmax_t , Cptrdiff_t , Csize_t , Cssize_t , Cuintmax_t und Cwchar_t . Diejenigen, die mit _t enden, sollten bleiben, da sie so benannt sind, dass sie mit ihren entsprechenden C-Typen übereinstimmen.

C_NULL ist der ungerade hier draußen und der einzige C-Alias, der einen Unterstrich enthält, der nicht in C gespiegelt ist (da dies in C nur NULL ). Wir könnten erwägen, dies CNULL .

  • [] C_NULL

Bitzählung

  • [] count_ones
  • [] count_zeros
  • [] trailing_ones
  • [] trailing_zeros
  • [] leading_ones
  • [] leading_zeros

Eine Erläuterung zum Umbenennen dieser Informationen finden Sie unter # 23531. Ich bevorzuge es sehr, die Unterstriche für diese sowie einige der vorgeschlagenen Ersetzungen in dieser PR zu entfernen. Ich denke, es sollte überdacht werden.

Unsichere Operationen

  • [] unsafe_copyto!
  • [] unsafe_load
  • [] unsafe_pointer_to_objref
  • [] unsafe_read
  • [] unsafe_store!
  • [] unsafe_string
  • [] unsafe_trunc
  • [] unsafe_wrap
  • [] unsafe_write

Es ist wahrscheinlich in Ordnung, diese so zu belassen, wie sie sind. Die Hässlichkeit des Unterstrichs unterstreicht weiter ihre Unsicherheit.

Indizierung

  • [] broadcast_getindex
  • [] broadcast_setindex!
  • [] to_indices

Anscheinend existieren broadcast_getindex und broadcast_setindex! . Ich verstehe nicht, was sie tun. Vielleicht könnten sie einen aussagekräftigeren Namen verwenden?

Interessanterweise wird die Einzelindexversion von to_indices , Base.to_index nicht exportiert.

Spuren

  • [] catch_backtrace
  • [x] catch_stacktrace -> stacktrace(catch_backtrace()) (# 25615)

Vermutlich sind dies die catch Blockäquivalente von backtrace bzw. stacktrace .

Aufgaben, Prozesse und Signale

  • [] current_task
  • [] task_local_storage
  • [] disable_sigint
  • [] reenable_sigint
  • [] process_exited
  • [] process_running

Streams

  • [] redirect_stderr
  • [] redirect_stdin
  • [] redirect_stdout
  • [x] nb_available -> bytesavailable (# 25634)

Es wäre schön, eine allgemeinere IO -> IO Umleitungsfunktion zu haben, in der all diese kombiniert werden könnten, z. B. redirect(STDOUT, io) , wodurch sowohl Unterstriche als auch Exporte entfernt werden.

Beförderung

  • [] promote_rule
  • [] promote_shape
  • [] promote_type

Siehe # 23999 für eine relevante Diskussion zu promote_rule .

Drucken

  • [x] print_with_color -> printstyled (siehe # 25522)
  • [] print_shortest (siehe # 25745)
  • [] escape_string (siehe # 25620)
  • [] unescape_string

escape_string und unescape_string sind insofern etwas seltsam, als sie in einem Stream gedruckt oder eine Zeichenfolge zurückgegeben werden können. Unter # 25620 finden Sie einen Vorschlag zum Verschieben / Umbenennen dieser.

Laden des Codes

  • [] include_dependency
  • [] include_string

include_dependency . Wird dies auch außerhalb von Base verwendet? Ich kann mir keine Situation vorstellen, in der Sie dies anstelle von include in einem typischen Szenario wünschen würden.

include_string . Ist das nicht nur eine offiziell genehmigte Version von eval(parse()) ?

Dinge, die ich nicht kategorisierte

  • [x] gc_enable -> GC.enable (# 25616)
  • [] get_zero_subnormals
  • [] set_zero_subnormals
  • [] time_ns

get_zero_subnormals und set_zero_subnormals könnten aussagekräftigere Namen vertragen. Müssen sie exportiert werden?

Alle 131 Kommentare

Entschuldigung, wenn dies nicht der geeignete Ort ist, um dies zu erwähnen, aber es wäre schön, in Zukunft konsistenter mit Unterstrichen in Funktionsnamen zu sein.

Nein, das ist ein guter Ort dafür. Und ja, wir sollten uns bemühen, alle Namen zu entfernen, bei denen Unterstriche erforderlich sind :)

  • Konsistente Behandlung von Eingabeargumenten für "Berechnen über diese [diese] Dimension [s]", welche Typen zulässig sind usw. Überlegen Sie, ob dies als Schlüsselwortargumente erwünscht sein könnte
  • Auflisten und Priorisieren unserer Was-kommt-zuerst-Konventionen in Bezug auf Funktionsargumente für Do-Blöcke, E / A-Argumente für Funktionen, die gedruckt werden, Ausgaben für In-Place-Funktionen usw. (Bearbeiten: Ich dachte, es gibt möglicherweise bereits eine offene Konvention dafür)

Es gab auch kürzlich einen Julep bezüglich der API für find und verwandter Funktionen: https://github.com/JuliaLang/Juleps/blob/master/Find.md

Sollten wir put! und take! auf Kanälen ablehnen (und vielleicht dasselbe für Futures tun), da wir push! und shift! auf ihnen haben? Ich schlage nur vor, 2 redundante Wörter in der API zu entfernen.

Ich bin misstrauisch, dass shift! benutzerfreundlich ist. Ein Kandidat ist fetch! Wir haben bereits fetch , die nicht mutierende Version von take!

Ref # 13538 # 12469

@amitmurthy @malmaud

Bearbeiten: Es wäre sogar sinnvoll, send und recv auf Kanälen wiederzuverwenden. (Ich bin überrascht, dass diese derzeit nur für UDPSockets verwendet werden.)

+1 für das Ersetzen von put! / take! durch push! / fetch!

Ich werde @inferred in @test_inferred umbenennen.

Stellen Sie sicher, dass die Spezialisierungen mit den allgemeineren Funktionen übereinstimmen, dh nicht mit # 20233.

Überprüfen Sie alle exportierten Funktionen, um festzustellen, ob sie beseitigt werden können, indem Sie sie durch Mehrfachversand ersetzen, z. B. print_with_color

Die typische Paarung ist push! und shift! wenn mit einer warteschlangenartigen Datenstruktur gearbeitet wird.

Wenn wir nicht die typische Namenspaarung für diese Art von Datenstruktur verwenden, weil wir befürchten, dass die Operation Kommunikationsaufwand mit sich bringt, der durch diese Namen nicht angemessen vermittelt wird, dann denke ich nicht, dass push! macht auch Sinn. send und recv könnten wirklich besser sein.

Überprüfen Sie möglicherweise noch einmal, ob es eine allgemeine Übereinstimmung gibt, ob Funktionen ein Tupel als letztes Argument oder ein Vararg verwenden.

Vielleicht zu groß für dieses Problem, aber es wäre gut, konsistente Regeln zu haben, wann Funktionen Fehler auslösen sollten und wann sie Nullable s oder Union s zurückgeben sollten (z. B. parse / tryparse , match usw.)

Kein Problem zu groß, @simonbyrne - das ist die

Übrigens: Dies ist nicht wirklich für bestimmte Änderungen (z. B. das Umbenennen bestimmter Funktionen) - es geht eher um Dinge, die wir überprüfen können. Öffnen Sie für bestimmte vorgeschlagene Änderungen einfach ein Problem, das diese Änderung vorschlägt.

Wir haben viele Tools wie @code_xxx , die mit zugrunde liegenden Funktionen wie code_xxx gepaart sind

Ich bin mir nicht sicher, ob es sich um das handelt, aber siehe CreateMacrosFrom.jl

  • Gibt an, ob die APIs für den "Ausgabetyp" den Elementtyp oder den Gesamtcontainertyp betreffen sollen (Ref. 11557 und 16740).
  • Dokumentieren Sie alle exportierten Funktionen (einschließlich Doctests).

Dokumentieren Sie alle exportierten Funktionen (einschließlich Doctests).

Wenn dies ein Teil davon ist, dann vielleicht auch: Denken Sie daran, Ihre Tests mit der Ausgabe- / PR-Nummer zu kennzeichnen. Es macht es viel einfacher zu verstehen, warum dieser Test da ist. Ich weiß, wie Git-Schuld funktioniert, aber beim Hinzufügen von Testsätzen (um nur ein Beispiel zu nennen) ist es manchmal ein Rätsel, was getestet wird, und es wäre großartig, wenn das Problem / die PR-Nummer immer vorhanden wäre.

@dpsanders : und exportierte Makros! zB @fastmath hat keine Dokumentzeichenfolge.

Dies ist sehr geringfügig, aber die Funktionen string und Symbol machen fast dasselbe und haben eine unterschiedliche Großschreibung. Ich denke, symbol wäre sinnvoller.

@amellnik Der Unterschied besteht darin, dass Symbol ein Typkonstruktor und string eine reguläre Funktion ist. IIRC hatten wir früher symbol aber es wurde zugunsten des Typkonstruktors veraltet. Ich bin nicht davon überzeugt, dass hierfür eine Änderung erforderlich ist, aber wenn überhaupt, sollten wir den Konstruktor String anstelle von string .

Wenn überhaupt, sollten wir den String-Konstruktor anstelle des Strings verwenden.

Nein, es handelt sich um verschiedene Funktionen, die nicht zusammengeführt werden sollten

julia> String(UInt8[])
""

julia> string(UInt8[])
"UInt8[]"

Nein, es handelt sich um verschiedene Funktionen, die nicht zusammengeführt werden sollten

Dies scheint eine Situation zu sein, in der string(args...) nur zugunsten von sprint(print, args...) veraltet sein sollte - sowohl string als auch String ist verwirrend. Wir könnten uns auf sprint(::typeof(print), args...) , um Leistungsverluste auszugleichen. In diesem Sinne könnte es auch sinnvoll sein, repr(x) für sprint(showall, args...) zu verwerfen.

Das klingt in Ordnung, obwohl es ziemlich normal erscheint, string aufzurufen, um etwas in einen String zu verwandeln ....

Das Aufrufen eines Strings, um etwas in einen String zu verwandeln, scheint ziemlich normal zu sein

Ja, aber hier kommt die Trennung zwischen String und string Spiel.

sprint(print, ...) fühlt sich überflüssig an. Wenn wir string loswerden, können wir sprint in string umbenennen, sodass wir string(print, foo) und string(showall, foo) was meiner Meinung nach gut liest .

Dies kann ein Fall sein, in dem die Konsistenz überbewertet wird. Ich denke, es ist in Ordnung, string(x) für "gib mir nur eine Zeichenfolgendarstellung von x" zu haben. Wenn es komplizierter wird, z. B. wenn Sie angeben müssen, welche Druckfunktion verwendet werden soll, ist die Verwendung eines anderen Namens wie sprint sinnvoll.

Es wäre auch in Ordnung für mich, String(UInt8[]) in etwas anderes umzubenennen und String anstelle von string . string gibt uns in Zukunft etwas mehr Flexibilität, um zu ändern, welche Art von Zeichenfolge wir zurückgeben, aber das scheint nicht wahrscheinlich zu sein.

Ist reinterpret(String, ::Vector{UInt8} sinnvoll oder ist dies ein Wortspiel auf reinterpret ?

Das scheint sinnvoll zu sein.

Ein Problem ist, dass diese Funktion manchmal kopiert wird, sodass dieser Name etwas irreführend ist.

Stimmt, aber Saiten sollen unveränderlich sein, also können wir wahrscheinlich damit durchkommen.

Es gibt auch eine String(::IOBuffer) -Methode, aber es sieht so aus, als ob diese auf readstring veraltet sein könnte.

Ich habe auch über Ihre vorgeschlagene API-Änderung nachgedacht, aber die Schnittstelle von string(a, b...) besteht darin, dass sie ihre Argumente stringifiziert und verkettet, und dies würde eine nervige Gotcha-Ausnahme für aufrufbare erste Argumente darstellen. Wenn wir die Verkettung von string entfernen, könnte dies funktionieren.

Ja angenommen; Konsistenz und Vermeidung von Fallstricken ist am wichtigsten.

Beachten Sie die Probleme Nr. 18326 und Nr. 3893 in der Kategorie "Dimensionsargumente".

Wenn ich einen anderen Punkt ansprechen kann: Sicherstellen, dass das Verhalten von Containern mit veränderlichen Stoffen sowohl dokumentiert als auch konsistent ist.

@ JaredCrean2 : näher erläutern, was du damit meinst?

Ich hoffe auf jeden Fall, dass es nicht darum geht, viele "defensive Kopien" anzufertigen.

Wenn ich beispielsweise ein Array von veränderlichen Typen habe und sort darauf aufrufe, zeigt das zurückgegebene Array auf dieselben Objekte wie das Eingabearray oder kopiert es die Objekte und macht das zurückgegebene Array auf Sie?

Die gleichen Objekte. Ich bin mir ziemlich sicher, dass alle unsere Methoden zum Sortieren, Getindexen, Filtern, Suchen usw. dieser Sammlung dieser Regel folgen, nicht wahr?

Ich glaube nicht, dass es in diesem Punkt an Klarheit oder Konsistenz mangelt - es sind immer die gleichen Objekte.

Tatsächlich denke ich, dass die einzige Standardfunktion, bei der dies nicht der Fall ist, deepcopy bei der der springende Punkt ist, dass Sie alle neuen Objekte erhalten.

Ist das irgendwo dokumentiert?

Nein - wir könnten, aber ich bin mir nicht sicher, wo es am besten wäre, es zu dokumentieren. Warum sollten Funktionen unnötig Kopien erstellen? Woher hast du den Eindruck, dass sie könnten?

Hallo. Ich habe keine Bemerkungen zur Datenserialisierung gesehen.

Früher oder später werden Julia-Programme geschrieben und öffentlich ausgeführt, Daten werden sich manchmal jahrelang schichten. Datenserialisierung zB. Die Kette: Objekt zu Bytes, die vom Typ gesteuert werden (möglicherweise über JSON oder ...), muss so erstellt werden, dass sie zeitbeständig ist. Das Nachdenken über semantische Versionierung und Web-API kann ebenfalls zählen.

Können wir erwarten, dass die Serialisierung für Benutzerdaten in der Nähe von https://github.com/JuliaLang/julia/blob/v0.5.1/base/serialize.jl bleibt?

Warum sollten Funktionen unnötig Kopien erstellen? Woher hast du den Eindruck, dass sie könnten?

Ich weiß nicht, ob sie es tun oder nicht. Soweit ich das beurteilen kann, ist das Verhalten undefiniert. Aus @ JeffBezansons Kommentar geht hervor, dass es Leute gibt, die sich dafür einsetzen, defensive Kopien

Sie scheinen eine Art Prinzip der geringsten Aktion zu implizieren, aber abhängig von den Details des Algorithmus wird die "geringste Aktion" mehrdeutig. Um Konsistenz über die API zu erreichen, sind meiner Meinung nach spezifischere Anleitungen erforderlich.

@ o314 : Dies ist ein Problem bei der Überprüfung der API-Konsistenz. Ich bin mir nicht sicher, wie die Serialisierung zusammenhängt.

@ JaredCrean2 : Ob das Objekt der obersten Ebene kopiert wird oder nicht, muss auf jeden Fall dokumentiert werden. Was ich sage ist, dass tiefere Objekte niemals kopiert werden, außer durch Deepcopy (offensichtlich).

Was ich sage ist, dass tiefere Objekte niemals kopiert werden, außer durch Deepcopy (offensichtlich).

Es gab kürzlich eine Diskussion darüber im Zusammenhang mit copy für einige der Array-Wrapper, z. B. SubArray und SparseMatrixCSC aber auch Symmetric , LowerTriangular . Es scheint mir, dass unter der oben genannten Richtlinie copy ein Noop für solche Wrapper-Typen wäre. Ist die von Ihnen erwähnte Richtlinie hier die richtige Abstraktionsebene? ZB denke ich, dass dies impliziert, dass sich das Verhalten von copy auf Array s zu einem Noop ändern sollte, wenn Array s in Julia implementiert wurden (einen Puffer umschließen).

Wenn die Konvention lautet, dass tiefere Objekte niemals kopiert werden, müssen sie nur noch dokumentiert werden. Die Dokumentation ist ein wirklich wichtiger Bestandteil einer API. Dieses Verhalten mag Ihnen offensichtlich erscheinen (vielleicht weil Sie Teile des Codes geschrieben haben), aber von außen ist es nicht so offensichtlich.

Edit: Andreas Post nicht gesehen. Das ist eine interessante Überlegung.

@StefanKarpinski Ich stimme Ihrem Punkt zu.
Und alle hier angesprochenen Hauptthemen sind sehr gut und klug.

Aber ich habe manchmal ein bisschen Angst vor dem Gleichgewicht zwischen Prozess und Daten in Julia:

Wir können sicher fortran oder c anrufen,
Aber Code wird genauso einfach in modernen Rechenzentren bereitgestellt werden, zum Beispiel. aws lambda mit seiner Funktion als Servicemuster. Wird Code über das Internet leicht aufrufbar sein, API öffnen?

Manchmal muss man die Funktionslast maßstabsgetreu senken (keine generischen Werte, keine Werte für die Funktionssignatur, keine höhere Ordnung für die öffentliche API) und systematischere Daten dahinter binden (json schema / openapi).

Ich habe gesehen, wie eine sehr gute Python-Bibliothek auf diese Weise versank, und das ist schade.

Ich denke, es ist ein entscheidender Punkt für eine Sprache 1.0, Daten und Funktionen ausgewogen und modular zu halten, damit sie problemlos im Web bereitgestellt werden können. Und für diese Funktion muss die Benutzeroberfläche bei Bedarf weniger tier- und rinderorientiert sein.

Vielleicht ist das nicht der Punkt in diesem Thema.

@StefanKarpinski Ich habe Ihren Beitrag möglicherweise falsch verstanden. Als Sie sagten

Ob das Objekt der obersten Ebene kopiert wird oder nicht, muss auf jeden Fall dokumentiert werden

Was bedeutet "Objekt der obersten Ebene"? Wenn ich x::Vector{MyMutableType} , ist das Objekt der obersten Ebene x oder die Elemente von x ?

Das Objekt der obersten Ebene bezieht sich auf x selbst, nicht auf die Elemente von x .

@andreasnoack Der Begriff des Objekts der obersten Ebene sollte sich auf die implementierte abstrakte Struktur beziehen, nicht auf Implementierungsdetails.

Vielleicht float und andere ähnliche Funktionen hinzufügen, die sowohl auf Typen als auch auf Werte wirken?

Wenn man sich die Versionshinweise zu 0.6 ansieht, scheint es seltsam, dass iszero(A::Array{T}) eingeführt wird, während viele andere Funktionen (z. B. sumabs , isinteger , isnumber ) über Arrays sind veraltet zugunsten von all(f,A) .

Es gibt null Arrays und sie sind null Elemente in ihrem Vektorraum. iszero testet generisch, ob etwas die additive Inverse ist, welche Null-Arrays sind.

Re. Konsistenz der Unterstriche in Funktionsnamen, hier ist ein Breadcrumb zu count_ones und count_zeros .

Es scheint mir, dass Sie, wenn Sie die Julia-API konsistent konsistent halten möchten, eine Software benötigen, mit der Sie (a) die API-Regeln / Konventionen angeben und (b) eine statische Analyse des zu erkennenden Julia-Codes durchführen können Abweichungen von diesen Regeln / Konventionen und (c) Vorschläge. Ein solches Tool würde sowohl Julia Base als auch allen Julia-Paketen zugute kommen. Ein neues Julia-Paket könnte den Trick machen. (Zunge in der Wange: Das erste, was dieses Paket tun sollte, ist, einen eigenen Namen vorzuschlagen: APICheck.jl, ApiCheck.jl, API_Check.jl, APIChecker.jl, JuliaAPIChecker.jl usw.) Ich bin ziemlich neu in Julia. Ich möchte also nicht die Führung übernehmen. Es würde mir jedoch nichts ausmachen, einen Beitrag zu leisten. Irgendwelche Vorschläge, wie man das in Gang bringt?

Wir würden das gerne in Lint.jl haben!

num2hex und hex2num (# 22031 und # 22088)

Ich glaube auch, dass Lint.jl das richtige Paket für die Julia API-Konsistenzprüfung ist. Aber wenn wir diesen Weg gehen, muss Stefans ursprüngliche Liste viel präziser gemacht werden. Wenn er beispielsweise schreibt: "Wir sollten sicherstellen, dass alle Sammlungen in DataStructures konsistente APIs haben", stellen sich folgende Fragen:

  • Was macht eine Datenstruktur zu einer Sammlung? (Liste der Sammlungen in der Basis)
  • Welche Funktionen muss eine Sammlung unterstützen? (Eine Tabelle mit Funktionen nach Sammlungen)
  • Wie sollte die Signatur jeder dieser Funktionen sein?
  • Sind die von Base für Sammlungen bereitgestellten APIs bereits konsistent?

Um solche Bestände und Analysen zu verwalten, möchten wir möglicherweise ein Projekt zum Julia-Repository (Projekt Nr. 8), zum JuliaPraxis-Repository (von TotalVerb offline vorgeschlagen) oder zum Lint-Repository hinzufügen. In diesem Fall müssten wir herausfinden, wem ein solches Projekt gehören würde, welche Personen von Anfang an einbezogen werden sollten und wer die endgültigen Entscheidungen darüber treffen sollte, was die Julia-Konventionen tatsächlich sind (zum Zweck des Flusens).

Bevor ich jedoch weiter in diese Richtung gehe , @StefanKarpinski fragen: Was sind Ihre Ideen zur Bearbeitung Ihrer Liste von Julia-API-Konsistenzproblemen?

Ich bin damit einverstanden, dass es eine gute Idee ist, dies speziell zu spezifizieren. Herauszufinden, was diese Liste sein sollte, ist Teil der Arbeit hier - wenn Sie einen Sprung hinein machen möchten, wäre das großartig.

Benötigen wir wirklich ein Base.datatype_module und ein Base.function_module?

Ein einheitliches Funktionsmodul (möglicherweise getmodule), das nach Datentyp und Funktion versendet, scheint mir konsistenter zu sein.

Was ist mit den Unterstrichen in @code_typed und Freunden?

Das ist eine gute Gelegenheit zum Refactoring (der angegebene Grund für das Unterstrichverbot). Sie könnten ein @code -Makro haben, wobei das erste Argument die Art von Code ist, die Sie wollen.

( @bramtayl , bitte denken Sie daran, Makros mit @code )

FWIW, Tab-Vervollständigung funktioniert nur mit Funktionsnamen. Es ist schön, @code_<TAB> ....

Wenn Refactoring in Betracht gezogen, aber abgelehnt wird, ist es umstritten, ob es Unterstriche gibt oder nicht, da der einzige Punkt des Unterstrichverbots darin besteht, das Refactoring zu fördern. In diesem Fall sollten Unterstriche gefördert werden, um die Sprache klarer zu machen

Unterstreichen Sie die Prüfung.

Gegenvorschlag: Wir prüfen diese Namen immer noch, fügen jedoch weitere Unterstriche hinzu, um das Lesen des Codes zu erleichtern (codetyped vs code_typed, isos2 vs is_os2).

Ich bin nicht absolutistisch. Ich denke, code_typed ist in Ordnung, es wird sinnvollerweise durch Tabulatoren vervollständigt, wie @KristofferC hervorhebt , und es ist nicht wirklich offensichtlich, was als Argument für die Auswahl der gewünschten Ausgabe zu übergeben ist.

Für mich scheint es eher so, als ob das Schiff mehr Unterstriche hinzugefügt hat, da wir im Grunde die Hälfte der Basis abwerten müssten. Als Beispiel gibt es 74 Prädikatfunktionen, die mit is und nur 6, die mit is_ . Was macht mehr Sinn, wenn man 6 oder 74 ablehnt?

Ok, hier gibt es mehrere widersprüchliche Ziele:

1) Namen besser lesbar machen
2) Reduzierung der Code-Abwanderung
3) Ermutigung zum Refactoring

Das Eliminieren von Unterstrichen durch Zusammenstoßen von Wörtern schlägt an allen drei Fronten fehl.

Dass show Methoden, die einen Stream akzeptieren, nicht ! -terminiert sind, scheint nicht mit der üblichen Konvention vereinbar zu sein? Ref. https://github.com/JuliaLang/julia/pull/22604/commits/db9d70a279763ded5088016d9c3d4439a49e3fca#r125115063. Beste! (Bearbeiten: Ich nehme an, dies entspricht write Methoden, die einen Stream akzeptieren.)

Es gibt Inkonsistenzen mit der Merkmals-API. Einige Merkmale werden berechnet, indem das Merkmal wie aufgerufen wird
TypeArithmetic(Float64)
während andere diese Funktion in Kleinbuchstaben geschrieben werden müssen:
iteratorsize(Vector{Float64})

Erwägen Sie, size -> shape (xref # 22665) umzubenennen.

Array{T,1}() sollte wahrscheinlich auch veraltet sein:

julia> Array{Int,1}()                                                                                                                  
0-element Array{Int64,1}                                                                                                               

julia> Array{Int,2}()                                                                                                                  
WARNING: Matrix{T}() is deprecated, use Matrix{T}(0, 0) instead.                                                                       

Habe über Sammlungen nachgedacht. Wir haben grundsätzlich drei Arten:

  • Einfache satzartige (oder taschenartige) Sammlungen, die nur einige Werte enthalten.
  • Array-ähnliche Sammlungen, die neben den Daten einen Index hinzufügen.
  • Diktartige Sammlungen, die Indizes als Teil der Daten enthalten, dh k=>v Paare.

Ich bin skeptisch gegenüber dem diktartigen Verhalten geworden. Der Kanarienvogel in der Kohlengrube ist map , wo das Arbeiten mit Schlüssel-Wert-Paaren nicht selbstverständlich ist, da Sie normalerweise den Schlüsselsatz nicht ändern möchten. Es ist auch möglich, dass Arrays und Dicts dieselbe Schnittstelle implementieren:

  • keys entspricht eachindex
  • mapindexed und filterindexed wären sowohl für Diktate als auch für Arrays nützlich. Diese sind wie Map und Filter, außer dass Sie Ihrer Funktion auch den Index des betreffenden Elements übergeben.
  • Arrays und Dicts (und benannte Tupel und möglicherweise andere Dinge) könnten einen pairs -Iterator verwenden, der im Grunde eine Verknüpfung für zip(keys(c), values(c)) .

Erwägen Sie, ind2sub und sub2ind umzubenennen, die anscheinend Matlabismen sind und einen nicht julianischen und seltsamen Namen für einen Nicht-Matlab-Benutzer haben. Mögliche Namen wären indice bzw. linearindice . Ich habe es nicht gewagt, eine PR zu machen, da ich nicht sicher bin, was die Leute darüber denken, aber ich werde es tun, wenn es Unterstützung gibt.

Gleiches gilt für rad2deg und deg2rad .

Ref. # 22791 ( select -> partialsort ). Beste!

Eines habe ich hier nicht gesehen: Gehen optionale Positionsargumente an erster oder letzter Stelle? Manchmal stehen optionale Positionsargumente an erster Stelle, wie in sum(f, itr) und rand([rng,] ..) . Aber anderswo gehen sie zuletzt, z. B. in median(v[, region]) oder split(s::AbstractString[, chars]) . Manchmal können sie zuerst oder zuletzt gehen, aber nicht beide! (Zum Beispiel kann mean zuerst eine Funktion oder zuletzt eine Dimension annehmen, aber nicht beide.)

Die aktuelle Sprachsemantik erzwingt, dass optionale Argumente als letztes verwendet werden: Sie können f(a, b=1) schreiben, aber nicht f(b=1, a) . Aber wenn alle optionalen Argumente als letztes gelten, was passiert dann mit praktischen Do-Blöcken?

Wenn nichts anderes, ist es eine kleine Warze, dass die Sprache Methoden wie diese definieren muss, von rand.jl : shuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a) . Die optionale Syntax für Positionsargumente sollte genau diesen Anwendungsfall berücksichtigen.

Vielleicht sollte in einem separaten Thema behandelt werden, aber es scheint möglich zu sein, die optionalen Argumente zu verschieben, wo immer Sie möchten. So würde beispielsweise f(a = 1, b, c = 2) f(x) = f(1, x, 2) und f(x, y) = f(x, y, 2)

xref # 22460 für einen (unbeliebten) Versuch, Standardargumente an einer beliebigen Position zu aktivieren.

Vielleicht benennen Sie warn in warning (Matlab verwendet dies auch), keine große Sache, aber dachte, ich würde es erwähnen?

Ich mag warn da es ein Verb ist, wie throw .

Das hat mich nur sehr verwirrt:

julia> f(;a=1,b=1) = a+b                                                                                                                              
f (generic function with 1 method)                                                                                                                    

julia> f(a=4,5)            # I intended to write f(a=4,b=5)                                                                                                                           
ERROR: MethodError: no method matching f(::Int64; a=4)                                                                                                
Closest candidates are:
  f(; a, b) at REPL[13]:1

Ich empfehle, beim Aufrufen von Funktionen nur Schlüsselwörter als letztes zuzulassen, ähnlich wie beim Definieren von Schlüsselwortfunktionen.

Ich empfehle, beim Aufrufen von Funktionen nur Schlüsselwörter als letztes zuzulassen, ähnlich wie beim Definieren von Schlüsselwortfunktionen.

Es gibt viele APIs, bei denen das Übergeben von Schlüsselwörtern an anderen Positionen sowohl nützlich als auch ergonomisch ist.

Gibt es aus Neugier eine definierte Bewertungsreihenfolge für Positions- und Keyword-Argumente? Ich habe ein paar ältere Probleme gesehen und https://docs.julialang.org/en/latest/manual/functions/#Evaluation -Scope-of-Default-Values-1 spricht über Bereiche, aber nichts, was ich gefunden habe, gibt an, ob z Argumente werden von links nach rechts ausgewertet, oder alle Positionsargumente werden vor allen Schlüsselwortargumenten ausgewertet, oder wenn keine definierte Auswertungsreihenfolge (oder etwas anderes) vorhanden ist.

@yurivish , Schlüsselwörter finden Sie in den Dokumenten (auch https://github.com/JuliaLang/julia/issues/23926). Für optionale ist die Geschichte etwas komplizierter, vielleicht lesen Sie hier . (Beachten Sie jedoch, dass Fragen besser unter https://discourse.julialang.org/ gestellt werden.)

Scheint das eigene Problem nicht wert zu sein, aber es scheint mir immer seltsam, dass bits(1) ein String bits(1) zurückgibt, es scheint, als sollte es BitVector oder Vector{Bool} .

Ich möchte eine Überprüfung der Methodentabellen vorschlagen, die für Function oder Callable versendet werden . Versuchen wir sicherzustellen, dass diese APIs so sind, wie wir sie wollen… und dass wir nicht die Gelegenheit verpassen, die Tabellen so umzustrukturieren, dass wir jedes Objekt als Entenaufruf zulassen können.

Was all und any betrifft, so scheinen diese unkompliziert auf all(f(x) for x in xs) , was bereits auf all(Generator(f, xs)) reduziert ist und daher keinen Overhead haben sollte.

Ich bin mir nicht sicher, ob es das ist, was Sie gemeint haben, aber ich dachte, es lohnt sich, nur für den Fall zu sagen: Ich bin hart dagegen, APIs im funktionalen Stil für Generatoren zu verwerfen. Wir haben any(f, x) und all(f, x) und sie sind weit verbreitet; -10000000 zum Entfernen dieser (oder solcher Methoden, wirklich).

Ich bin Pro Generator. Scheint ein grundlegender Baustein für fauler Programmierung zu sein und sollte exportiert werden. all(Generator(f, xs)) manchmal für definierte Funktionen bequemer als all(f(x) for x in xs) . Auch +10000000, um das Gleichgewicht wiederherzustellen

Ich bevorzuge hier, wenn möglich, weniger Syntax. Wenn es einfach und lesbar und performant ist, die Idee von "nimm xs, wende f auf alles an und gib wahr zurück, wenn all dies wahr ist" auszudrücken, warum sollten wir es dann in ein Verb setzen?

Wenn das Problem das unnötige Substantiv x in f(x) for x in xs , dann @bramtayls Vorschlag, Generator exportieren (vielleicht mit einem besseren Namen wie Map ?) macht Sinn.

Dinge wie all(isnull, x) sind viel einfacher als all(isnull(v) for v in x) . Wir haben die Funktion allnull von NullableArrays zugunsten von all(isnull, x) abgelehnt. Wenn diese Syntax wegfallen würde, müssten wir sie wahrscheinlich wieder einführen.

Wie wäre es, wenn Sie strwidth in stringwidth umbenennen (ich denke, dies ist die einzige exportierte String-Manipulationsfunktion, die String in str abgekürzt hat).

Eigentlich wurde es in textwidth (https://github.com/JuliaLang/julia/pull/23667).

IMO, dieses Problem ist zu weit gefasst, um den Meilenstein von 1.0 zu erreichen, da wir in Kürze mit dem Einfrieren von Funktionen beginnen möchten. Möglicherweise benötigen wir mehrere Eigentümer und weisen Funktionssätze zur Überprüfung zu, wenn wir dies tun möchten.

Dies ist auch ein weiterer Ort, an dem FemtoCleaner viele Dinge nach 1.0 automatisch aktualisieren kann, obwohl es schön wäre, alles in Ordnung zu bringen.

Nur ein Kommentar zur Textbreite:

INFO: Testing Cairo
Test Summary:   | Pass  Total
Image Surface   |    7      7
Test Summary:   | Pass  Total
Conversions     |    4      4
Test Summary:   | Pass  Total
TexLexer        |    1      1
WARNING: both Compat and Cairo export "textwidth"; uses of it in module Main must be qualified
Samples        : Error During Test
  Got an exception of type LoadError outside of a <strong i="6">@test</strong>
  LoadError: UndefVarError: textwidth not defined
  Stacktrace:
   [1] include_from_node1(::String) at .\loading.jl:576
   [2] include(::String) at .\sysimg.jl:14
   [3] macro expansion at C:\Users\appveyor\.julia\v0.6\Cairo\test\runtests.jl:86 [inlined]
   [4] macro expansion at .\test.jl:860 [inlined]
   [5] anonymous at .\<missing>:?
   [6] include_from_node1(::String) at .\loading.jl:576
   [7] include(::String) at .\sysimg.jl:14
   [8] process_options(::Base.JLOptions) at .\client.jl:305
   [9] _start() at .\client.jl:371
  while loading C:\Users\appveyor\.julia\v0.6\Cairo\samples\sample_pango_text.jl, in expression starting on line 28

Die Fehlermeldung scheint ziemlich klar zu sein, was das Problem ist? Cairo müssen die Basismethode erweitern.

help?>  Base.textwidth
  No documentation found.

  Binding Base.textwidth does not exist.

julia> versioninfo()
Julia Version 0.6.0
julia> Compat.textwidth
textwidth (generic function with 2 methods)

Ich hatte keinen Zweifel, dass die Nachricht (die ich über Travis erhalten habe) in Ordnung ist, aber warum exportiert Compat Textbreite, wenn sie nicht in 0.6 ist?

Weil das der Punkt von Compat ist? Diese Diskussion geht jedoch weit über den Rahmen hinaus, daher schlage ich vor, dass wir sie im Diskurs fortsetzen oder nachlassen können.

Ich schlage vor, copy in shallowcopy und deepcopy in copy ändern, da ich vor kurzem einige Zeit gebraucht habe, um zu erkennen, dass es sich bei der Kopie um eine "flache" Kopie handelt Die von mir geschriebene Funktion mutierte das Array von Arrays. Ich denke, es wäre viel intuitiver, wenn copy eine "tiefe" Kopie erstellen würde und so etwas wie shallowcopy für flache Kopien verwendet wird? Ich weiß es jetzt Wann sollte deepcopy , aber ich denke, dass viele andere Benutzer auf dasselbe Problem stoßen werden.

Lassen Sie uns bitte versuchen, dieses Problem aus Gründen der API-Konsistenz beizubehalten, und nicht mit "bestimmten Dingen, die ich nicht mag".

Associative Der Name scheint ziemlich inkonsistent mit allen anderen Typnamen in Julia zu sein.

Erstens sind Typen normalerweise keine Adjektive. Das Substantiv ist Association und wird zumindest von einigen Mathematica-Dokumenten verwendet, die ich gefunden habe.

Ich denke, dass AbstractDict weitaus konsistenter mit anderen Typen wie AbstractArray , AbstractRange , AbstractSet und AbstractString , die jeweils haben Ein prototypischer Beton gibt Dict , Array , Range , Set und String .

Unsere Ausnahmetypen sind weit verbreitet: Einige heißen FooError , andere BarException ; Einige werden exportiert, die meisten nicht. Dies könnte aus Gründen der Konsistenz einen Durchgang verwenden.

Was wäre also bevorzugt, FooError oder BarException ? Exportiert oder nicht?

Für mich beinhaltet BarException irgendwo ein Anhebungs- / Fangmuster.

Ich bevorzuge viel, und einige andere in der Funktionswelt verwenden auch das Muster Some / None (*), bei dem der Kontrollfluss direkter und vorhersehbarer ist.

Also +1 für FooError

(*) Some / Void ex Optional in Julia # 23642.

Sind diese Dinge angesichts des Einfrierens der Funktionen noch auf dem Tisch? Ich würde besonders gerne optionale oder Schlüsselwortargumente behandeln, aber die Liste der Funktionen mit mehreren optionalen Argumenten (der klarste Fall für die Verwendung von Schlüsselwortargumenten) ist ziemlich lang.

Bitte sehen Sie sich das an! Ich habe keine Chance bekommen, diese Themen systematisch durchzugehen.

Übrigens habe ich eine Inkonsistenz bei der Benennung von Merkmalen festgestellt : Wir haben iteratorsize , iteratoreltype , aber IndexStyle , TypeRangeStep , TypeArithmetic und TypeOrder . Es sieht so aus, als ob die CamelCase-Varianten zahlreicher und neuer sind. Vielleicht sollten wir diese Konvention also überall anwenden?

Diese sollten auf jeden Fall konsistent gemacht werden. Willst du eine PR machen?

Ich denke, dies sollte als Teil von https://github.com/JuliaLang/julia/pull/25356 behoben werden

BEARBEITEN: siehe auch https://github.com/JuliaLang/julia/issues/25440

Dies geschieht meistens oder kann in 1.x-Versionen erfolgen. Ich kann die Kontrollkästchen aktualisieren, aber wir haben sie gerade beim Triage-Aufruf durchgesehen und alles außer # 25395 und der Unterstrichprüfung ist abgeschlossen.

Unterstreichen Sie die Prüfung

Das Folgende ist eine Analyse aller aus Base exportierten Symbole, die Unterstriche enthalten, nicht veraltet sind und keine Zeichenfolgenmakros sind. Die Hauptsache hier ist, dass dies nur exportierte Namen sind; Dies schließt keine nicht exportierten Namen ein, die wir den Leuten sagen, dass sie qualifiziert anrufen sollen.

Ich habe die Dinge nach Kategorien getrennt. Hoffentlich ist das nützlicher als nervig.

Reflexion

Wir haben folgende Makros mit entsprechenden Funktionen:

  • [] @code_llvm , code_llvm
  • [] @code_lowered , code_lowered
  • [] @code_native , code_native
  • [] @code_typed , code_typed
  • [] @code_warntype , code_warntype

Welche Änderungen auch immer auf die Makros angewendet werden, sollte auf ähnliche Weise auf die Funktionen angewendet werden.

  • [x] module_name -> nameof (# 25622)
  • [x] module_parent -> parentmodule (# 25629, siehe # 25436 für einen früheren Umbenennungsversuch)
  • [x] method_exists -> hasmethod (# 25615)
  • [x] object_id -> objectid (# 25615)
  • [] pointer_from_objref

pointer_from_objref könnte vielleicht einen aussagekräftigeren Namen vertragen, vielleicht so etwas wie address ?

Aliase für C interop

Die Typ-Aliase, die Unterstriche enthalten, sind C_NULL , Cintmax_t , Cptrdiff_t , Csize_t , Cssize_t , Cuintmax_t und Cwchar_t . Diejenigen, die mit _t enden, sollten bleiben, da sie so benannt sind, dass sie mit ihren entsprechenden C-Typen übereinstimmen.

C_NULL ist der ungerade hier draußen und der einzige C-Alias, der einen Unterstrich enthält, der nicht in C gespiegelt ist (da dies in C nur NULL ). Wir könnten erwägen, dies CNULL .

  • [] C_NULL

Bitzählung

  • [] count_ones
  • [] count_zeros
  • [] trailing_ones
  • [] trailing_zeros
  • [] leading_ones
  • [] leading_zeros

Eine Erläuterung zum Umbenennen dieser Informationen finden Sie unter # 23531. Ich bevorzuge es sehr, die Unterstriche für diese sowie einige der vorgeschlagenen Ersetzungen in dieser PR zu entfernen. Ich denke, es sollte überdacht werden.

Unsichere Operationen

  • [] unsafe_copyto!
  • [] unsafe_load
  • [] unsafe_pointer_to_objref
  • [] unsafe_read
  • [] unsafe_store!
  • [] unsafe_string
  • [] unsafe_trunc
  • [] unsafe_wrap
  • [] unsafe_write

Es ist wahrscheinlich in Ordnung, diese so zu belassen, wie sie sind. Die Hässlichkeit des Unterstrichs unterstreicht weiter ihre Unsicherheit.

Indizierung

  • [] broadcast_getindex
  • [] broadcast_setindex!
  • [] to_indices

Anscheinend existieren broadcast_getindex und broadcast_setindex! . Ich verstehe nicht, was sie tun. Vielleicht könnten sie einen aussagekräftigeren Namen verwenden?

Interessanterweise wird die Einzelindexversion von to_indices , Base.to_index nicht exportiert.

Spuren

  • [] catch_backtrace
  • [x] catch_stacktrace -> stacktrace(catch_backtrace()) (# 25615)

Vermutlich sind dies die catch Blockäquivalente von backtrace bzw. stacktrace .

Aufgaben, Prozesse und Signale

  • [] current_task
  • [] task_local_storage
  • [] disable_sigint
  • [] reenable_sigint
  • [] process_exited
  • [] process_running

Streams

  • [] redirect_stderr
  • [] redirect_stdin
  • [] redirect_stdout
  • [x] nb_available -> bytesavailable (# 25634)

Es wäre schön, eine allgemeinere IO -> IO Umleitungsfunktion zu haben, in der all diese kombiniert werden könnten, z. B. redirect(STDOUT, io) , wodurch sowohl Unterstriche als auch Exporte entfernt werden.

Beförderung

  • [] promote_rule
  • [] promote_shape
  • [] promote_type

Siehe # 23999 für eine relevante Diskussion zu promote_rule .

Drucken

  • [x] print_with_color -> printstyled (siehe # 25522)
  • [] print_shortest (siehe # 25745)
  • [] escape_string (siehe # 25620)
  • [] unescape_string

escape_string und unescape_string sind insofern etwas seltsam, als sie in einem Stream gedruckt oder eine Zeichenfolge zurückgegeben werden können. Unter # 25620 finden Sie einen Vorschlag zum Verschieben / Umbenennen dieser.

Laden des Codes

  • [] include_dependency
  • [] include_string

include_dependency . Wird dies auch außerhalb von Base verwendet? Ich kann mir keine Situation vorstellen, in der Sie dies anstelle von include in einem typischen Szenario wünschen würden.

include_string . Ist das nicht nur eine offiziell genehmigte Version von eval(parse()) ?

Dinge, die ich nicht kategorisierte

  • [x] gc_enable -> GC.enable (# 25616)
  • [] get_zero_subnormals
  • [] set_zero_subnormals
  • [] time_ns

get_zero_subnormals und set_zero_subnormals könnten aussagekräftigere Namen vertragen. Müssen sie exportiert werden?

+1 für method_exists => methodexists und object_id => objectid . Es ist auch irgendwie albern, dass catch_stacktrace überhaupt existiert. Es kann bis zu seiner Definition stacktrace(catch_backtrace()) veraltet sein.

Wie denken wir darüber, C_NULL unterstreichen? Ich habe mich ziemlich daran gewöhnt, aber ich kaufe auch das Argument, dass keiner der anderen C* Namen einen Unterstrich hat.

Die anderen C-Namen sind Typen, während C_NULL eine Konstante ist. Ich finde es gut, wie es ist und befolge die Namensrichtlinien.

und folgt den Benennungsrichtlinien.

Wie das?

Konstanten sind oft alle Großbuchstaben mit Unterstrichen - C_NULL folgt dem. Wie @ iamed2 sagte, ist es ein Wert, kein Typ, daher gilt die Namenskonvention Cfoo nicht unbedingt.

Ich habe fälschlicherweise gedacht, dass https://github.com/JuliaLang/julia/blob/master/doc/src/manual/variables.md#stylistic -conventions auf Konstanten verweist, aber das tut es nicht. Es sollte wahrscheinlich.

Ich schlage eine konsistente, mathematisch fundierte Schnittstelle für allgemeine Hilbert-Räume vor, in denen Vektoren keine Julia-Arrays sind. Funktionsnamen wie vecdot , vecnorm usw. könnten durchaus durch die allgemeinen Konzepte von inner und norm wie in https: // github beschrieben. com / JuliaLang / Julia / Issues / 25565.

Wie ich einige Male gesagt habe, ist dies kein Sammelproblem für Dinge, die man ändern möchte.

Ich glaube, die einzigen Artikel, die für 1.0 unter diesem Dach verbleiben, sind # 25501 und # 25717.

Ich würde gerne etwas mit (get|set)_zero_subnormals aber vielleicht ist die beste kurzfristige Lösung, sie einfach nicht zu exportieren.

Was wahrscheinlich überprüft werden sollte, ist, wie Zahlen im Zusammenhang mit Erfassungsvorgängen wie map und collect . Es wurde darauf hingewiesen, dass der erstere einen Skalar zurückgibt, der letztere jedoch ein 0D-Array zurückgibt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen