Go: Vorschlag: spec: binäre Integer-Literale

Erstellt am 27. Feb. 2017  ·  91Kommentare  ·  Quelle: golang/go

Derzeit unterstützt Go zusätzlich zu den standardmäßigen Dezimalliteralen, die Sie erwarten würden, oktale und hexadezimale Integer-Literale. Um diese Gruppe abzurunden, schlage ich vor, auch binäre Integer-Literale hinzuzufügen. Sie würden in der Form als neues Präfix für Integer-Literale erscheinen: 0b oder 0B .

Ursprünglicher Haftungsausschluss

Dies war mein erster Tauchgang in den Go-Quellcode und in erster Linie eine Lernerfahrung für mich, um meine Füße nass zu machen, Änderungen einzureichen und was nicht. In diesem Sinne bin ich für jede Kritik, Kommentare und Anregungen dankbar.

Das "Warum": Stand der Technik

Binäre Literale existieren oder sind auch in Mainstream-Sprachen erschienen, einschließlich:

Alle oben genannten Fälle haben sich auf eine Konvention festgelegt, bei der Binärliterale mit 0b oder 0B vorangestellt werden, was darauf hindeutet, dass dies auch für Go eine ziemlich bequeme und vernünftige Wahl wäre, um unnötige Erfindungen zu vermeiden und Bereitstellung von Ähnlichkeit für Programmierer, die aus diesen anderen oben genannten Sprachen kommen.

Das "Warum": Fortsetzung

Ich habe es geschafft, einige frühere Diskussionen zu diesem Thema zu finden, allerdings nachdem ich das Feature bereits implementiert hatte und es mehr mit der Änderung der oktalen Syntax als speziell mit binären Literalen zu tun hat. Aber https://github.com/golang/go/issues/12711#issuecomment -142338246 von @griesemer erwähnt, dass "sowohl das 'o' für Oktal als auch das 'b' für binäre Notation im Design von Go diskutiert wurden. Es ist einfach nicht genug für das Geld." Ich sehe dies jedoch nicht als gutes Argument dagegen, der Sprache etwas so Einfaches hinzuzufügen. Vor allem angesichts der Tatsache, dass heutzutage immer mehr Sprachen die Syntax für binäre Literale übernommen haben, scheint es, dass die früheren Go-Designentscheidungen unter einem neuen Licht betrachtet werden müssen.

Anwendungsbeispiel

const (
    SOME_MASK   = 0b00001111
    SOME_FLAG_A = 0b00000001
    SOME_FLAG_B = 0b00000010
    SOME_FLAG_C = 0b00000100
    SOME_FLAG_D = 0b00001000
)

Implementierung

Wie ich bereits sagte, war dies eher eine Lernerfahrung für mich, ich habe bereits Änderungen bereit, die diese Funktion implementieren:

CL-37502- Spezifikation: Syntax für binäre Integer-Literale angeben
CL-37503 cmd /compile/internal/syntax:
CL-37504 go/scanner: binäre Integer-Literale scannen
CL-37505 strconv: unterstützt das Parsen von binären Integer-Literalen
CL-37506- Test: int_lit um binäre

FrozenDueToAge Go2 LanguageChange NeedsDecision Proposal Proposal-Accepted

Hilfreichster Kommentar

Schauen wir uns an, warum die oben genannten Sprachen vorangekommen sind und Unterstützung für binäre Literale hinzugefügt haben. Beginnen wir mit C++14, da es das erste auf der Liste ist. Was waren die Punkte, die James Dennett, damals Google-Mitarbeiter, vorbrachte?

Die Verwendung eines 0b/0B-Präfixes für binäre Literale ist eine vorhandene GCC-Erweiterung (die auch von Clang unterstützt wird) und hat dieselbe Syntax wie Java 7, Python und D.

Warum sollte Go von diesem besonderen Punkt profitieren?

Vertrautheit mit der Sprache.

Viele Entwickler wechseln von Programmiersprache zu Programmiersprache. Korrigieren Sie mich, wenn ich falsch liege, aber wir versuchen alle, was wir aus einer Sprache wissen, in einer anderen. Man könnte in gewisser Weise sagen, dass Gos Vertrautheit mit C und C++ die Art von Entwicklern anzog, die ein bestimmtes Feature wie GC wollten, aber andere Sprachen nicht mochten. Dies ist einer der Gründe, warum sich das Unternehmen, bei dem ich derzeit ein Praktikum mache, für Go entschieden hat.

Lassen Sie uns neben erfahrenen Entwicklern auch einen Blick darauf werfen, welchen Vorteil die Vertrautheit für Anfänger hat. Nehmen wir auch den Anwendungsfall von Flags, den @eddieringle erwähnt hat. Einem kompletten Anfänger zu erklären, wie Flags funktionieren, ist viel schwieriger, wenn Sie es in oktaler oder hexadezimaler Form erklären müssen, da die Person diese ebenfalls lernen muss.

Schließlich möchte ich hier hinzufügen, dass der Zweck jeder Sprache (zumindest das hoffe ich) darin besteht, sauberen Code zu schreiben. Und ich denke, darüber sind wir uns alle einig. Wenn man sich den Code einer anderen Person ansieht, wird sofort ohne Erklärung klar, dass es sich bei einer Liste von binären Literalkonstanten um Flags handelt. Dasselbe ist viel weniger einfach, wenn Sie hexadezimal oder oktal verwenden. Unten ist ein Vergleich.

// Hexadecimal
const (
    MASK          = 0x1E
    DEFAULT_COLOR = 0x00
    BOLD          = 0x01
    UNDERLINE     = 0x02
    FLASHING_TEXT = 0x04
    NO_CHANGE     = 0x08
)

// Octal
const (
    MASK          = 036
    DEFAULT_COLOR = 00
    BOLD          = 01
    UNDERLINE     = 02
    FLASHING_TEXT = 04
    NO_CHANGE     = 010
)

// Binary
const (
    MASK          = 0b11110
    DEFAULT_COLOR = 0b00000
    BOLD          = 0b00001
    UNDERLINE     = 0b00010
    FLASHING_TEXT = 0b00100
    NO_CHANGE     = 0b01000
)

Ich denke, dass man sich keine Gedanken darüber machen muss, dass die letzten Konstanten für Flags verwendet werden. Dies sind auch sehr wenige Flaggen. Denken Sie also daran, dass sich dies definitiv summiert, wenn Sie mehr Flaggen haben. Die erste Konstante 0x1E kann definitiv den Kopf verdrehen, wenn sie ohne Kontext deklariert wird. Die alleinige Verwendung von Binärliteralen kann darauf hinweisen, dass eine Variable als Flag verwendet werden könnte.

Das erwähnte C++-PDF verweist weiterhin auf die oben genannten Sprachen zur Unterstützung. Schauen wir uns diese also als nächstes an. Ich habe den (ursprünglichen?) Vorschlag von Derek Foster im Jahr 2009 für binäre Literale in JDK gefunden. Quelle

Die erste Frage, der ich vollkommen zustimme, ist, warum es im JDK eine oktale Darstellung gibt, im JDK jedoch keine binäre Darstellung. In den letzten Jahren habe ich mir nie gedacht: "Oh, Oktale würden meinen Code sauberer machen!" Dies bezieht sich jedoch auf den vorherigen Punkt, den ich gemacht habe: Vertrautheit . Es gibt jedoch eine Sache, die es zu meinem zuvor gemachten Punkt hinzufügt:

Wenn die zu behandelnden Daten jedoch grundsätzlich bitorientiert sind, erfordert die Verwendung von Hexadezimal zur Darstellung von Bitbereichen einen zusätzlichen Übersetzungsgrad für den Programmierer, und dies kann oft zu einer Fehlerquelle werden. [...] dann muss ein Programmierer, der nach dieser Spezifikation codiert, jeden solchen Wert von seiner binären Darstellung in hexadezimal umwandeln. [...] In den meisten Fällen machen Programmierer diese Übersetzungen im Kopf und bekommen sie HOFFNUNG richtig. Es können sich jedoch leicht Fehler einschleichen, und die erneute Überprüfung der Ergebnisse ist nicht einfach genug, um häufig durchgeführt zu werden.

Hexadezimale und oktale Notationen, die hauptsächlich in Hardware anstelle von binär verwendet werden, können zu menschlichen Fehlern führen. In dem Vergleich, den ich zuvor gegeben habe, habe ich überprüft, was ich mit meinem Kopf gemacht habe, indem ich das, was ich für oktal hielt, in Google eingegeben habe, was meine Antworten bestätigte. Ich bin mir meiner Sache automatisch sicher, wenn ich es binär schreibe, aber nicht, wenn ich es hexadezimal oder oktal schreibe. Und egal wie oft Sie dies am Tag tun, es erschwert das Schreiben von Code, da Sie sich die binäre Form im Kopf ausdenken müssen und dabei Fehler machen können.

Um tiefer in die Frage einzusteigen, warum es eine oktale Notation, aber keine binäre Notation gibt, muss ich noch eine weitere Frage stellen, die auch von Derek Foster, dem Autor des binären wörtlichen Vorschlags für das JDK, gestellt wurde: "Warum hat Go sich für die Verwendung entschieden? das Präfix 0 für oktale Notationen?" @griesemer kommentierte, dass wir bei der Implementierung neuer Funktionen nicht

Warten wir ab, was andere Leute sagen, bevor wir zur Waffe springen. Vielen Dank.

Aber hat Go bei der Implementierung der oktalen Notation nicht übersprungen? Wenn das Argument "weil andere Sprachen es tun", warum kann dieses Argument dann nicht für binäre Literale verwendet werden? Wenn nicht, was war dann der Grund, warum das Präfix 0 für oktale Notationen es in die Sprache geschafft hat, wenn es die Leute verwirrt?

Jemand könnte fälschlicherweise denken, dass "0b1" denselben Wert wie die Hexadezimalzahl "0xB1" darstellt. Beachten Sie jedoch, dass dieses Problem für Oktal/Dezimal seit vielen Jahren besteht (Verwechslung zwischen "050" und "50") und kein großes Problem zu sein scheint.

- Derek Foster

Es scheint nicht mehr Argumente für binäre Literale zu geben, da wir uns alle in unseren Köpfen darauf beziehen. Deshalb denke ich, dass die Vorschläge für andere Sprachen so kurz waren wie diese. Es ist jedoch kein Grund, es so schnell zu schließen.

Alle 91 Kommentare

Das ist schon mal aufgetreten. Die Einführung ist mit einem erheblichen Arbeitsaufwand verbunden, so dass die Compiler- und Spezifikationsänderungen trivial sind. Aber es gibt viele Bibliotheken, die auch konsistent gemacht werden sollten (strconv, math/big, etc.).

Wenn wir in diese Richtung etwas ändern, sollte es gründlicher sein und willkürliche Grundlagen unterstützen. Ich bin so wie es ist dagegen.

@griesemer Ja, die Änderungen, die ich einreichen strconv (nach meinem Verständnis ist dies tatsächlich erforderlich, um diese Änderung zu unterstützen).

@griesemer Ich bin jedoch nicht einverstanden, dass jede Änderung willkürliche Basen unterstützen sollte oder sonst überhaupt keine Änderung vorgenommen wird. Nach vorheriger Lektüre klingt es so, als wäre dies ein gutes Ziel für Go2; Dies ist lediglich ein Polieren von Go1 mit Syntax, die Entwickler anderer Sprachen erwarten könnten, wenn sie Go verwenden. (dh Base-2 ist ein häufiger Fall, wahrscheinlich häufiger als oktal; Base-14 oder was-hast-du ist weniger so.)

CL https://golang.org/cl/37503 erwähnt dieses Problem.

CL https://golang.org/cl/37504 erwähnt dieses Problem.

CL https://golang.org/cl/37502 erwähnt dieses Problem.

CL https://golang.org/cl/37505 erwähnt dieses Problem.

CL https://golang.org/cl/37506 erwähnt dieses Problem.

Ich sehe dies jedoch nicht als gutes Argument dagegen, der Sprache etwas so Einfaches hinzuzufügen.

Es ist auch kein besonders starkes Argument dafür, sie hinzuzufügen.

IMHO müssen Sie den Abschnitt "Warum" erweitern, um genau zu erklären, welche Vorteile die Unterstützung von Binärliteralen den Leuten bringen wird, die go-Code schreiben.

Ich finde sie nicht besonders nützlich; hex ist ein viel lesbareres und kompakteres Format für Literale, die eine "Bit-Ebenen-Bedeutung" haben.

Sie haben ein "Anwendungsbeispiel" gegeben, aber es ist nicht sehr überzeugend. Ich würde diese Konstanten mit 0xf s und Verschiebungen für die anderen schreiben.

@EddieRingle Dieser Vorschlag wurde weder umfassend diskutiert noch akzeptiert. Bitte spammen Sie uns nicht mit Code-Reviews zu. Das Go-Team hat genug mit eigentlich wichtiger Arbeit zu tun.

Es ist jedem klar, dass es trivial ist, der Sprache ein einfaches Feature hinzuzufügen. Es ist auch klar, dass viele Leute dieses Feature mögen würden (mir selbst hätte es irgendwann gefallen). Aber das gesagt, nur weil man es kann, ist kein Argument, das man sollte. Jede noch so kleine und einfache Ergänzung einer Sprache hat langfristige Kosten. Wenn wir dies akzeptieren, wird es in Zukunft noch schwieriger, einen allgemeineren Mechanismus zu haben, und wir müssen abwärtskompatibel bleiben.

Warten wir ab, was andere Leute sagen, bevor wir zur Waffe springen. Vielen Dank.

Erinnerung an unsere No-Me-Too-Richtlinie: https://golang.org/wiki/NoMeToo

Meinungen ohne konstruktiven Inhalt können mit den Emoji-Reaktionen von Github geäußert werden.

@ALTree

IMHO müssen Sie den Abschnitt "Warum" erweitern, um genau zu erklären, welche Vorteile die Unterstützung von Binärliteralen den Leuten bringen wird, die go-Code schreiben.

Ich finde sie nicht besonders nützlich; hex ist ein viel lesbareres und kompakteres Format für Literale, die eine "Bit-Ebenen-Bedeutung" haben, IMO.

Ich würde eigentlich das Gegenteil behaupten. Hex ist in vielen Fällen kompakter, ja, aber binäre Literale wären eine exakte Darstellung auf "Bit-Ebene" und daher so lesbar wie möglich.

@griesemer

Dieser Vorschlag wurde weder breit diskutiert noch angenommen. Bitte spammen Sie uns nicht mit Code-Reviews zu. Das Go-Team hat genug mit eigentlich wichtiger Arbeit zu tun.

Entschuldigung. Es war ursprünglich eine einzige Änderung, aber da es so aussieht, als ob die Go-Richtlinie darin besteht, Commits basierend auf dem betroffenen Bereich der Codebasis aufzuteilen, habe ich sie letztendlich aufgeteilt. Mir war nicht bewusst, dass der Bot hier bei jeder Änderung individuelle Kommentare abgeben würde. Ich wäre jedoch nicht so kalt, es als Spam zu bezeichnen oder zu behaupten, dass meine Bemühungen, meine Freizeit zu nutzen, unwichtig sind.

Jede noch so kleine und einfache Ergänzung einer Sprache hat langfristige Kosten. Wenn wir dies akzeptieren, wird es in Zukunft noch schwieriger, einen allgemeineren Mechanismus zu haben, und wir müssen abwärtskompatibel bleiben.

Wie bereits erwähnt, würde die Allzweck-Route (die ich auch bevorzugen würde) auch dazu führen, dass die vorhandene (verwirrende) oktale Syntax veraltet / entfernt wird, nicht wahr? Ich hatte das Gefühl, dass die allgemeine Syntax ( 2r0010 oder 2x0010 für Basis-2 zum Beispiel) eine Erfindung für Go2 war, wo Breaking Changes sowieso willkommen wären.

Abgesehen von einem möglichen Go2, um die Aussage zu adressieren, dass "_wenn wir dies akzeptieren, wird es in Zukunft noch schwieriger werden, einen allgemeineren Mechanismus zu haben_": Ich verstehe einfach nicht, wie das wahr ist. Das Hinzufügen des binären Literalpräfixes wäre orthogonal zu einer alternativen Allzwecksyntax, insbesondere zu der, die Sie in #12711 beschrieben haben (tatsächlich kollidiert diese Syntax direkt mit hexadezimalen Literalen, aber nicht mit dieser vorgeschlagenen binären Literalsyntax). Sie würden nebeneinander existieren, genau wie die allgemeine Syntax mit den vorhandenen Oktal-, Hex- und Dezimalliteralen.

Entschuldigung. Es war ursprünglich eine einzige Änderung, aber da es so aussieht, als ob die Go-Richtlinie darin besteht, Commits basierend auf dem betroffenen Bereich der Codebasis aufzuteilen, habe ich sie letztendlich aufgeteilt. Mir war nicht bewusst, dass der Bot hier bei jeder Änderung individuelle Kommentare abgeben würde. Ich wäre jedoch nicht so kalt, es als Spam zu bezeichnen oder zu behaupten, dass meine Bemühungen, meine Freizeit zu nutzen, unwichtig sind.

Es ist nicht nur so, dass der Bot E-Mails zu CLs sendet, sondern dass jede per E-Mail gesendete CL eine Aufforderung an einen Go-Überprüfer ist, Zeit damit zu verbringen, sie zu überprüfen.

Die 0b Syntax ist schön, weil sie bekannt ist, aber wenn das wahre Ziel darin besteht, der Sprache einfach binäre Literale hinzuzufügen, würde ich die generische Lösung der vertrauten viel vorziehen.

Gibt es einen technischen Grund, warum die generische Option nicht vor 2.0 implementiert werden kann? Ich hatte in letzter Zeit eine Reihe von Fällen, in denen binäre Literale gegenüber Hex bevorzugt wurden, und es wäre schön, diese Option in 1.9 oder 1.10 zu haben, anstatt (möglicherweise viele Jahre) bis 2.0 zu warten.

@wedow Ich denke, es würde helfen, bestimmte reale Fälle zu sehen, in denen binäre Literale nützlich sind. Bitte teilen Sie die Fälle mit, in denen binäre Literale hilfreich wären. Vielen Dank.

Ich sehe "sollte willkürliche Basen unterstützen" nicht als lohnenden Einwand. Es erhöht die Komplexität/Kosten für einen geringen oder keinen zusätzlichen Nutzen. In all den Jahren, in denen ich gehackt habe, sind die nützlichen Basen, von denen ich gehört habe, dass sie 2, 8, 10, 12 und 16 und möglicherweise 64 verwenden möchten (wir haben schließlich die base64-Kodierung). .

Schauen wir uns an, warum die oben genannten Sprachen vorangekommen sind und Unterstützung für binäre Literale hinzugefügt haben. Beginnen wir mit C++14, da es das erste auf der Liste ist. Was waren die Punkte, die James Dennett, damals Google-Mitarbeiter, vorbrachte?

Die Verwendung eines 0b/0B-Präfixes für binäre Literale ist eine vorhandene GCC-Erweiterung (die auch von Clang unterstützt wird) und hat dieselbe Syntax wie Java 7, Python und D.

Warum sollte Go von diesem besonderen Punkt profitieren?

Vertrautheit mit der Sprache.

Viele Entwickler wechseln von Programmiersprache zu Programmiersprache. Korrigieren Sie mich, wenn ich falsch liege, aber wir versuchen alle, was wir aus einer Sprache wissen, in einer anderen. Man könnte in gewisser Weise sagen, dass Gos Vertrautheit mit C und C++ die Art von Entwicklern anzog, die ein bestimmtes Feature wie GC wollten, aber andere Sprachen nicht mochten. Dies ist einer der Gründe, warum sich das Unternehmen, bei dem ich derzeit ein Praktikum mache, für Go entschieden hat.

Lassen Sie uns neben erfahrenen Entwicklern auch einen Blick darauf werfen, welchen Vorteil die Vertrautheit für Anfänger hat. Nehmen wir auch den Anwendungsfall von Flags, den @eddieringle erwähnt hat. Einem kompletten Anfänger zu erklären, wie Flags funktionieren, ist viel schwieriger, wenn Sie es in oktaler oder hexadezimaler Form erklären müssen, da die Person diese ebenfalls lernen muss.

Schließlich möchte ich hier hinzufügen, dass der Zweck jeder Sprache (zumindest das hoffe ich) darin besteht, sauberen Code zu schreiben. Und ich denke, darüber sind wir uns alle einig. Wenn man sich den Code einer anderen Person ansieht, wird sofort ohne Erklärung klar, dass es sich bei einer Liste von binären Literalkonstanten um Flags handelt. Dasselbe ist viel weniger einfach, wenn Sie hexadezimal oder oktal verwenden. Unten ist ein Vergleich.

// Hexadecimal
const (
    MASK          = 0x1E
    DEFAULT_COLOR = 0x00
    BOLD          = 0x01
    UNDERLINE     = 0x02
    FLASHING_TEXT = 0x04
    NO_CHANGE     = 0x08
)

// Octal
const (
    MASK          = 036
    DEFAULT_COLOR = 00
    BOLD          = 01
    UNDERLINE     = 02
    FLASHING_TEXT = 04
    NO_CHANGE     = 010
)

// Binary
const (
    MASK          = 0b11110
    DEFAULT_COLOR = 0b00000
    BOLD          = 0b00001
    UNDERLINE     = 0b00010
    FLASHING_TEXT = 0b00100
    NO_CHANGE     = 0b01000
)

Ich denke, dass man sich keine Gedanken darüber machen muss, dass die letzten Konstanten für Flags verwendet werden. Dies sind auch sehr wenige Flaggen. Denken Sie also daran, dass sich dies definitiv summiert, wenn Sie mehr Flaggen haben. Die erste Konstante 0x1E kann definitiv den Kopf verdrehen, wenn sie ohne Kontext deklariert wird. Die alleinige Verwendung von Binärliteralen kann darauf hinweisen, dass eine Variable als Flag verwendet werden könnte.

Das erwähnte C++-PDF verweist weiterhin auf die oben genannten Sprachen zur Unterstützung. Schauen wir uns diese also als nächstes an. Ich habe den (ursprünglichen?) Vorschlag von Derek Foster im Jahr 2009 für binäre Literale in JDK gefunden. Quelle

Die erste Frage, der ich vollkommen zustimme, ist, warum es im JDK eine oktale Darstellung gibt, im JDK jedoch keine binäre Darstellung. In den letzten Jahren habe ich mir nie gedacht: "Oh, Oktale würden meinen Code sauberer machen!" Dies bezieht sich jedoch auf den vorherigen Punkt, den ich gemacht habe: Vertrautheit . Es gibt jedoch eine Sache, die es zu meinem zuvor gemachten Punkt hinzufügt:

Wenn die zu behandelnden Daten jedoch grundsätzlich bitorientiert sind, erfordert die Verwendung von Hexadezimal zur Darstellung von Bitbereichen einen zusätzlichen Übersetzungsgrad für den Programmierer, und dies kann oft zu einer Fehlerquelle werden. [...] dann muss ein Programmierer, der nach dieser Spezifikation codiert, jeden solchen Wert von seiner binären Darstellung in hexadezimal umwandeln. [...] In den meisten Fällen machen Programmierer diese Übersetzungen im Kopf und bekommen sie HOFFNUNG richtig. Es können sich jedoch leicht Fehler einschleichen, und die erneute Überprüfung der Ergebnisse ist nicht einfach genug, um häufig durchgeführt zu werden.

Hexadezimale und oktale Notationen, die hauptsächlich in Hardware anstelle von binär verwendet werden, können zu menschlichen Fehlern führen. In dem Vergleich, den ich zuvor gegeben habe, habe ich überprüft, was ich mit meinem Kopf gemacht habe, indem ich das, was ich für oktal hielt, in Google eingegeben habe, was meine Antworten bestätigte. Ich bin mir meiner Sache automatisch sicher, wenn ich es binär schreibe, aber nicht, wenn ich es hexadezimal oder oktal schreibe. Und egal wie oft Sie dies am Tag tun, es erschwert das Schreiben von Code, da Sie sich die binäre Form im Kopf ausdenken müssen und dabei Fehler machen können.

Um tiefer in die Frage einzusteigen, warum es eine oktale Notation, aber keine binäre Notation gibt, muss ich noch eine weitere Frage stellen, die auch von Derek Foster, dem Autor des binären wörtlichen Vorschlags für das JDK, gestellt wurde: "Warum hat Go sich für die Verwendung entschieden? das Präfix 0 für oktale Notationen?" @griesemer kommentierte, dass wir bei der Implementierung neuer Funktionen nicht

Warten wir ab, was andere Leute sagen, bevor wir zur Waffe springen. Vielen Dank.

Aber hat Go bei der Implementierung der oktalen Notation nicht übersprungen? Wenn das Argument "weil andere Sprachen es tun", warum kann dieses Argument dann nicht für binäre Literale verwendet werden? Wenn nicht, was war dann der Grund, warum das Präfix 0 für oktale Notationen es in die Sprache geschafft hat, wenn es die Leute verwirrt?

Jemand könnte fälschlicherweise denken, dass "0b1" denselben Wert wie die Hexadezimalzahl "0xB1" darstellt. Beachten Sie jedoch, dass dieses Problem für Oktal/Dezimal seit vielen Jahren besteht (Verwechslung zwischen "050" und "50") und kein großes Problem zu sein scheint.

- Derek Foster

Es scheint nicht mehr Argumente für binäre Literale zu geben, da wir uns alle in unseren Köpfen darauf beziehen. Deshalb denke ich, dass die Vorschläge für andere Sprachen so kurz waren wie diese. Es ist jedoch kein Grund, es so schnell zu schließen.

Hier ist eine weitere Option, die mir klarer erscheint als jede der ganzzahligen Konstanten.

// Shifts
const (
    MASK          = 0x1e
    DEFAULT_COLOR = 0
    BOLD          = 1<<0
    UNDERLINE     = 1<<1
    FLASHING_TEXT = 1<<2
    NO_CHANGE     = 1<<3
)

(Und sollte mask nicht 0xf sein, nicht 0x1e?)

Ich bin etwas dagegen, binäre Konstanten hinzuzufügen, zumindest in Go 1. Ich wäre jedoch dafür, sie in Go 2 hinzuzufügen. Der Grund für den Unterschied ist, dass, wenn jemand aus irgendeinem Grund bei Go 1.8 festsitzt, wenn Go 1.9 mit binären Konstanten herauskommt, wenn einer der (transitiven) Importe des Codes dieser Person binäre Konstanten verwendet, sie ihre eigenen nicht mehr bauen können Projekt mit Go 1.8. Sie müssten Anbieter oder Upgrades. Das Hinzufügen einer vorwärts-inkompatiblen Funktion ist mit bestimmten Kosten verbunden, die gegen ihren Nutzen abwägen sollten.

Ich stimme zu, dass ich keine Notwendigkeit für Basen außerhalb von {2,8,10,16} sehe. Die Argumentation für Oktal scheint besonders wackelig zu sein, ich wäre dafür, Oktal in Go 2 zu entfernen.

@randall77 Ich bin nicht der Meinung, dass das Schalten sauberer aussieht. In meinem Kopf stelle ich sie immer noch als Binärzahlen dar und werde es wahrscheinlich immer tun. Es würde es einfacher machen, diese Berechnungen, die ich in meinem Kopf mache, zu entfernen.

(Und sollte mask nicht 0xf sein, nicht 0x1e?)

Der Name MASK wurde lediglich dem JDK-Vorschlag entnommen und 0x1E und Hexadezimalzahlen bereits für Verwirrung sorgen.

Ich kann den Punkt verstehen, den Sie vorbringen wollen, um es auf Go 2 zu verschieben. Aber ich bin nicht der Meinung, dass wir Projekte unterstützen müssen, die ihre Go-Version von 1.9 auf 1.8 herabstufen. Es würde den Umgang mit Sprachen zu einem Albtraum machen. Ich weiß jedoch nicht, wie Go das sieht, es wäre am klügsten, der Kompatibilität von Go zu folgen.

Ich unterstütze Ihre Position zur Entfernung von Oktal in Go 2 von ganzem Herzen.

Ich habe gerade meinen vorherigen Kommentar noch einmal gelesen (insbesondere "Das Go-Team hat genug mit Arbeit zu tun, die eigentlich wichtig ist"). Ich möchte mich für diese Aussage entschuldigen, die eine ziemlich beleidigende Formulierung dessen war, was ich eigentlich sagen wollte. Lassen Sie mich es also noch einmal versuchen, etwas mehr ausarbeiten und diesmal hoffentlich den richtigen Ton finden:

Wir freuen uns über gut begründete Vorschläge und ggf. mit prototypischen Umsetzungen. Der Vorschlagsprozess von Go ist jedoch absichtlich leichtgewichtig, und der Vorschlagende erfordert keine zusätzliche Arbeit, es sei denn, er wird angefordert oder zum Verständnis des Vorschlags erforderlich. Das Versenden von Änderungslisten, die nicht angefordert werden und/oder kein Problem beheben, ist kontraproduktiv, da sich jemand die Zeit nehmen muss, sie sich anzusehen (wenn auch nur, um sie zu verschieben oder zu schließen). Ein besserer Ansatz, wenn man den Code im Voraus prototypisieren/schreiben möchte, besteht darin, auf die Änderungen an anderer Stelle zu verlinken (z. B. ein privates GitHub-Commit). Dies lässt dem Go-Team und externen Mitwirkenden die Wahl: Sie können entscheiden, ob sie sich diesen Code ansehen oder sich anderweitig auf Elemente mit höherer Priorität konzentrieren möchten. Vielen Dank.

@griesemer Gotcha, ich verstehe und das macht Sinn. Ich nahm an, dass das Go-Team sein Gerrit behandelte, wie AOSP es tut, und dachte, dass meine Änderungen dort existieren könnten, während dies diskutiert wurde. Das Verlinken zu einem Branch hier auf GitHub ist sowieso weniger Arbeit, also ist es eine Win-Win-Situation, denke ich. :)

Ich habe die Arbeit tatsächlich zuerst gemacht, da mein Hauptziel darin bestand, den Compiler zu hacken. Es war danach, dass ich mich entschieden habe, es als Vorschlag einzureichen.

@AndreasBackx Die führende 0 für Oktal in Go wurde in Ausgabe #151 diskutiert. Siehe auch #12711.

Bei der Definition von 1-Set-Bit-Konstanten ist Shifting besser lesbar als 0b00001000..00 aus dem einfachen Grund, dass Sie in der Shift-Version nicht viele Nullen auf dem Bildschirm zählen müssen, nur um zu verstehen, welches Bit gesetzt ist ; Sie haben gerade den Verschiebungswert gelesen.

0b100000000000000000000000 vs 1 << 23

Soweit die Verwendung in der realen Welt geht, besteht ein übliches Verfahren zur Codierung von Ganzzahlen mit variabler Länge darin, das High-Bit für "Weiterlesen" zu verwenden. Ich musste es verwenden, um Git-Packfiles zu extrahieren. Hier ist der Code zum Extrahieren der unteren Bits in verschiedenen Basen:

b & 127
b & 0x1f
b & 0177
b & 0b01111111

Ich persönlich denke, dass die Binärversion die Absicht deutlicher zeigt.

Sie haben weiterhin die oben erwähnte Schichtoption
Wenn Sie denken, dass es nicht lesbar ist, verwenden Sie eine Hilfsfunktion

b & ^(^0 << 7)
b & mask(7)

@AndreasBackx , 1<<12 ist klarer als 0b0001000000000000 weil ich nicht all diese Nullen zählen muss. Es ist offensichtlich, dass es sich um eine Maske handelt, da 12 zwischen 11 und 13 liegt oder iota . Wenn ein beliebiges Muster übereinstimmen muss, z. zehn, so wie man mal Tabellen lernt, ist 65 ASCII A usw. Hex ist eine dichtere Darstellung, die für den menschlichen Leser leichter zu analysieren ist.

@randall77 , sind 0644, 02775 usw. ohne Oktal nicht etwas langweilig? Deshalb geht es immer noch rund.

@RalphCorderoy : Ja, es scheint mir, dass Oktal nur aus dem Grund überlebt, ein os.FileMode konstruieren.
0664 = 6<<6 + 6<<3 + 4 , was nicht allzu langweilig ist. Es wäre besser, wenn os symbolische Konstanten zur Verfügung stellen würde, um dies einfacher oder zumindest klarer zu machen.

Wir wissen bereits, wie wir das Problem des Zählens von Nullen vermeiden können: Wir sollten 0b1e10 , um 1 gefolgt von 10 Nullen in binärer Form zu bedeuten. Zugegeben, dies würde besser funktionieren, wenn wir eine Möglichkeit hätten, binäre Konstanten zu verketten, anstatt sie hinzuzufügen.

Ich habe die Arbeit tatsächlich zuerst gemacht, da mein Hauptziel darin bestand, den Compiler zu hacken.

Exzellent. Wenn Sie einige Ideen für Orte haben möchten, an denen Sie den Compiler weiter hacken können, während dies diskutiert wird, können Sie mir gerne eine E-Mail schreiben - (github-Benutzername) @ gmail.

@RalphCorderoy 1<<12 ist klarer als 0b0001000000000000, weil ich nicht all diese Nullen zählen muss.

Eine Lösung für dieses Problem wäre, eine Art Trennung zuzulassen. Java lässt Unterstriche in numerischen Literalen zu. Es wurde kurz in #42 diskutiert, aber es gab nicht viele Argumente dagegen, wenn es überhaupt Kommentare zu diesem Thema gab.

Die Lösung von @ianlancetaylor sollte vielleicht auch in Betracht gezogen werden.

Es ist offensichtlich, dass es sich um eine Maske handelt, da die 12 zwischen 11 und 13 liegt oder Jota verwendet.

Es tut mir leid, aber das ist vielleicht bei dir der Fall. Aber nicht für alle anderen.

Wenn ein beliebiges Muster übereinstimmen muss, z. zehn, so wie man Zeittabellen lernt, ist 65 ASCII A usw.

Dies lässt Raum für Fehler im Code, wie von mir bereits erwähnt und Vorschläge für andere Sprachen gemacht, die dies als triftigen Grund befunden haben. Sie gehen hier auch davon aus, dass jeder "Programmierer" Hex aus dem Kopf kennt und das ist nicht der Fall. Sie können mit viel Hardware arbeiten, aber die meisten Leute tun es nicht. Auf jeden Fall würden Anfänger die binären Literale der hexadezimalen Darstellung vorziehen.

Hex ist eine dichtere Darstellung, die für den menschlichen Leser einfacher zu analysieren ist.

Bedeutet dicht, dass es sauberer ist? Nein tut es nicht. Die Leute schreiben die ganze Zeit Einzeiler für verrückte Dinge und der Grund dafür, dass diese etwas beeindruckend sind, ist, dass dieser Code so dicht und unlesbar ist, dass wir uns alle fragen, welche Hexerei sich hinter der Bedeutung jedes Charakters verbirgt.

1 << 10 ist viel klarer als 0b1e10 .

Ich finde binäre Literale schwer zu lesen. Sehr oft rundet das, was Sie brauchen, auf drei oder vier Bit-Segmente auf, die viel einfacher und weniger fehleranfällig in oktaler oder hexadezimaler Form zu lesen und zu schreiben sind. Wenn sich die Dinge nicht so gleichmäßig abrunden, ist eine Verschiebung auch viel einfacher zu lesen und zu schreiben und weniger fehleranfällig.

Eine Form der Verkettung würde das Lesen und Schreiben von Binärliteralen auf Kosten der Inkonsistenz erleichtern. Warum können binäre Literale verkettet werden, aber kein anderer Typ von numerischen Literalen? Warum nicht hexen? An dieser Stelle wird diese Diskussion grenzenlos.

Persönlich würde ich eine Art generischer Radix-Mechanismus bevorzugen. Ich glaube nicht, dass binäre Literale genug in die Tabelle einbringen (und ich schreibe nur Low-Level-Code).

Außerdem bin ich mir ziemlich sicher, dass wir diese Diskussion schon mehrmals hatten.

(Als Randbemerkung, der Untergang von Oktal wurde stark übertrieben. Octal ist über das Festlegen von Dateimodi hinaus nützlich. Ich verwende sicherlich mehr Oktalliterale als binäre Literale.)

Es überrascht mich ein wenig, dass so viele persönliche Meinungen als Argumente für einen Sprachwechsel geäußert werden. Ich bin mir nicht sicher, wie ich Kommentare in Bezug darauf quantifizieren soll, wie nützlich Sie sie persönlich finden würden.

Wenn persönliche Gefühle aus irgendeinem Grund Verdienstpunkte haben, werde ich willkürlich sagen, dass ich binäre Literale in Java verwende, und ich kann meine Meinung dazu bestätigen, indem ich sage, dass ich seit 100 Jahren programmiere und ein Auto besitze.

Als nächstes zu diskutieren, ob es einfacher ist, Shifting zum Definieren von Masken zu verwenden, ist wie zu argumentieren, dass gregorianische Kalender einfacher zu verwenden sind als chinesische Kalender. Nur weil Sie es einfacher finden, heißt das nicht, dass jeder dies tut. Die Tatsache, dass binäre Literale in anderen Sprachen existieren, sollte wahrscheinlich ein Hinweis darauf sein, dass jemand sie nützlich fand, um zu fördern, dass das Shifting-Argument kein großes Argument ist, da es einfach nur eine Alternative ist.

Das ist schon mal aufgetreten. Die Einführung ist mit einem erheblichen Arbeitsaufwand verbunden, so dass die Compiler- und Spezifikationsänderungen trivial sind. Aber es gibt viele Bibliotheken, die auch konsistent gemacht werden sollten (strconv, math/big, etc.).

Dies ist ein solides Argument gegen diesen Vorschlag, und ich würde das Zögern bei Änderungen, die einen erheblichen Arbeitsaufwand verursachen, voll und ganz verstehen.

Ich würde eigentlich das Gegenteil behaupten. Hex ist in vielen Fällen kompakter, ja, aber binäre Literale wären eine exakte Darstellung auf "Bit-Ebene" und daher so lesbar wie möglich.

Das Lustige am Lernen von Binärdateien ist, dass Sie Binärdateien tatsächlich lesen und schreiben und dann mathematische Berechnungen ausführen müssen. Das Schreiben in Hex oder Dezimal oder Oktal oder Base64 (lul) kann indirekt beim Lernen von Binärdateien helfen, aber ich habe gehört, dass es nützlich ist, nur das zu lernen, was Sie direkt lernen möchten (wahrscheinlich jedoch nur eine Meinung).

Persönlich würde ich eine Art generischer Radix-Mechanismus bevorzugen.

Ich wünschte, jede Sprache hätte dies in wörtlicher Form.

@randall77 : Wie in #151 angegeben, gibt es mehrere Gründe, Oktal zu halten. Ja, eines ist die Einstellung von Dateimodi, aber das ist das letzte wichtige. Die anderen beiden sind die Änderung der Semantik, die zu einem Integer-Literal würde, das mit 0 beginnt, und die Bedeutung der Sicherheitsportierung von Code aus jeder anderen C-ähnlichen Sprache, in der Oktalkonstanten diese Syntax haben. Es stimmt, dass keines davon überzeugend ist, aber zusammengenommen treffen sie auf die Latte. Jedenfalls ist das Thema entschieden, zumindest für Go 1.

Was binäre Konstanten angeht, glaube ich nicht, dass sie ihr Gewicht haben. Nur sehr wenige Programme würden davon profitieren, und selbst dann ist der Nutzen gering.

@robpike Es wäre sicher, alles zu kompilieren, das wie eine oktale Konstante aussah (beginnt mit 0 aber nicht "0").

Lassen wir das für Go 2.

Warum warten? Es bricht nichts.
Am Montag, 6. März 2017 um 15:19 Uhr schrieb Russ Cox

Lassen wir das für Go 2.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/golang/go/issues/19308#issuecomment-284535766 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/ABLfW7bN2NicSthvEvMeGEhqExg2et-qks5rjHhtgaJpZM4MNgUY
.

@DocMerlin , weil Go keine Sprache ist, die ständig Funktionen

@DocMerlin Ich möchte dem Kommentar von @bradfitz hinzufügen, dass wir in der Vergangenheit Ausnahmen gemacht haben, wenn dringende Bedürfnisse bestanden. Hier besteht eindeutig kein dringender Bedarf.

Dies sind auch sehr wenige Flaggen. Denken Sie also daran, dass sich dies definitiv summiert, wenn Sie mehr Flaggen haben.
SOME_FLAG_D = 0b0000000001000000000000000000000

Ist das auf einen Blick 2^19 oder 2^20? Sehen Sie das Problem?

Danke @davecheney , ich habe den Thread

Es ist offensichtlich, dass es keine Anwendungsfälle gibt, in denen eine Routine, die die Bitmanipulation von Ganzzahlen handhabt, aufgrund des Fehlens von Binärliteralen nicht korrekt ausgedrückt werden kann, und es wird nichts an Leistung gewonnen, wenn Ganzzahldaten in einer Basis gegenüber einer anderen ausgedrückt werden.

Es gibt jedoch viele binäre Codierungssituationen (Videocodecs, Datenkomprimierung, binäre Netzwerkprotokolle usw.), in denen Bitmasken, binäre Konstanten und andere Bitmap-Daten im Quellcode lesbarer gemacht werden können, wenn die Daten in Basis 2 ausgedrückt werden.

Es ist eine Frage der Lesbarkeit und des Stils für Leute, die mit Bitmap-Daten umgehen.

Lesbarkeit und Stil sind die gleichen Gründe, warum die oktale Ganzzahl-Literalnotation von Go am ersten Tag unterstützt wurde. Die Aufnahme der Unterstützung für oktale Integer-Literale ist höchstwahrscheinlich eine Entscheidung, die mit der Handhabung von Unix-Dateiberechtigungen zu tun hat. Heutzutage ist es schwer, sich viele praktische Anwendungen der Oktalnotation vorzustellen, abgesehen von der Legacy-Unterstützung von Berechtigungen im Unix-Stil und der Lesbarkeit dieser Daten im Code.

Oktal-Unterstützung ist dennoch hilfreich, um zu zeigen, dass es in strconv nur zwei einfache Funktionen gibt, die mit der Handhabung von Oktal-Strings beauftragt sind.

archive/tar/strconv.go:func (p *parser) parseOctal(b []byte) int64
archive/tar/strconv.go:func (f *formatter) formatOctal(b []byte, x int64)

Um die Änderungsauswirkungen des Hinzufügens von Unterstützung für binäre Literale sehr grob einzuschätzen, besteht eine mögliche Methode darin, den Code-Footprint einer gleichwertigen Unterstützung für Oktal zu überprüfen wird unterstützt.

In meiner aktuellen lokalen Kopie zeigt eine grobe Suche, dass die meisten davon Parse- und Formatierungsoperationen sind.

vxv@vxs :/gosource$ grep -i -r oktal * | wc -l
73
vxv@vxs :/gosource$ grep -i -r oktal * | grep "func" | wc -l
2

Zugegeben, dies ist eine triviale und einfältige Suche, aber die Ausmaße des Problems scheinen keine unüberwindbare Aufgabe zu sein.

Kein Problem. Um es festzuhalten, ich habe keinen Hund in diesem Rennen, ich bin nur hier, um die Probleme zu bearbeiten. Es liegt an anderen, über das Schicksal dieses Vorschlags für go 2 zu entscheiden

Es gibt jedoch viele binäre Codierungssituationen (Videocodecs, Datenkomprimierung, binäre Netzwerkprotokolle usw.), in denen Bitmasken, binäre Konstanten und andere Bitmap-Daten im Quellcode lesbarer gemacht werden können, wenn die Daten in Basis 2 ausgedrückt werden.

Ich habe alle oben genannten Funktionen verwendet, und ich hätte nie gedacht, dass Base 2 für diese Vorteile haben könnte. Würden Sie ein konkretes Beispiel nennen, um mich vom Gegenteil zu überzeugen?

Die Lesbarkeit sollte ein Hauptgrund für die Implementierung binärer Literale sein. Ich schreibe derzeit eine Engine, die die Vorteile der Bitpositionierung nutzt, und ich verwende uint16, uint32 für mehrere Anwendungsfälle und jeder Slice/Abschnitt dieser uints repräsentiert unterschiedliche Informationen.

Im Schach verwenden wir codierte Züge, indem wir Flags, from und to position in ein uint16 einfügen. Es wäre schön, eine binäre literale Implementierung zu sehen, damit der Code nur für sich alleine zeigen kann, welche Abschnitte sich auf welche Informationen beziehen.

...
constexpr uint_fast16_t FLAG_SPECIAL1  {0b0010000000000000};
constexpr uint_fast16_t FLAG_SPECIAL0  {0b0001000000000000};
constexpr uint_fast16_t RANGE_FLAG     {0b1111000000000000};
constexpr uint_fast16_t RANGE_FROM     {0b0000111111000000};
constexpr uint_fast16_t RANGE_TO       {0b0000000000111111};

Dies ist mein Codebeispiel aus C++17. In Go sieht es jedoch so aus:

const FlagSpecial1 uint16 = 8192
const FlagSpecial2 uint16 = 4096
const RangeFlag uint16 = 61440
const RangeFrom uint16 = 4032
const RangeTo uint16 = 63

Im Wesentlichen nützlich, um sauberen und einfachen Code für jeden zu schreiben, der mit Bits und Masken arbeitet.

Kann Go keinen Precompiler dafür bekommen und dann musst du nichts umschreiben? Denn schließlich ist es Ästhetik (in meinen Augen).

Welches Bit ist gesetzt in (c++)

constexpr uint_fast16_t FLAG_SPECIAL0  {0b0001000000000000};

vs

welches Bit ist gesetzt in (Go)

const FlagSpecial0 = 0x10000

Ich bin wohl nicht der einzige, der erst im späteren Fall sofort sagen kann.

Mit dem 0b00..-Ansatz können Sie es sehen, ohne Hex-Zahlen kennen zu müssen. Es ist einfacher zu lesen, wenn Sie eine große Liste von uint16 haben. Zu verstehen, dass sich das gesetzte Bit an der Position 13 befindet, da die Größe aufgelistet ist, ist in dem von Ihnen angegebenen Beispiel einfacher als die Verwendung von Hex. 1<<13 , wäre viel besser als Hex und Sie müssen keine Werte nachschlagen, Sie können es sich einfach ansehen und wissen, welche Bits anvisiert werden. Aber für einen Bereich oder mehrere gesetzte Bits kann es einfacher sein, nur ein binäres Literal zu verwenden.

Wenn ich mir die späteren Fälle wie 61440 anschaue, bin ich beeindruckt, dass Sie es sofort erkennen können, und Sie denken, dass es einfacher ist zu wissen, welche Bits mit Dezimalzahlen gesetzt sind als mit einem binären Literal, aber nicht jeder sieht dies.

Aber Sie haben die anderen Fälle wie 0b0000111111000000 einfach ignoriert, was 0xfe0 oder 4064 dezimal ist. Meiner Meinung nach ist das mit binärem Literal sauberer. 16 Bit sind eine größere Zahl, aber schauen Sie sich Bytes an:

0b11101010 vs. 0xea . Sie müssen nicht einmal überlegen, was anvisiert wird, Sie wissen es einfach, sobald Sie einen Blick darauf werfen.

@andersfylling , Wenn Sie Bitmasken programmieren, müssen Sie wirklich Hex lesen können: RangeFlag wäre nicht 61440, sondern 0xf000, was sofort klar macht, dass es sich um das oberste Nibble der 16 Bits handelt.

Für diejenigen, die denken, dass sie neue Erkenntnisse zu diesem Thema haben, können Sie bitte alle Kommentare von oben durchgehen und insbesondere Brads Hinweis auf die NoMeToo-Richtlinie beachten, bevor Sie den Rest von uns aus unserem Schlaf wecken.

Hex- und Bitverschiebung erledigen alles für mich (plus die Oktaldateiberechtigungen), aber ich frage mich, ob das Erlernen der Bitmanipulation in C mit binären Integer-Literalen möglicherweise einfacher war. Ich mag, wie die obigen Beispiele im Binärformat aussehen. Vielleicht würde ich dies für kleine Masken oder zum Verschieben kleiner Masken verwenden.

x := y & (0b101 << 8)

(Bearbeiten: Der bessere Go-Weg ist x := y & 0b101<<8 )

Ich bin heute auf diesen Mangel an Funktionen gestoßen. In meinem Beispielanwendungsfall verwende ich das ganzzahlige Wochentagfeld eines Datums (0..6 bedeutet Sonntag..Samstag) und vergleiche es mit einer Präferenz-Bitmaske. Da die Quelle der Ganzzahl programmgesteuert ist, definiere ich nicht für jeden Wochentag einen Satz von Konstanten (mein Code hat keinen Grund, jemals speziell über SONNTAG zu sprechen), daher ist die 1 << 3-Syntax hier nicht nützlich. Ich möchte jedoch einen Standardwert für die Präferenz-Bitmaske, der vielleicht 0b0111110 wäre. Offensichtlich ist es einfach, diesen Standard als Dezimal (126) oder Hex (0x7e) zu schreiben, aber es ist wesentlich klarer, ihn in Binärform zu schreiben.

Betreff: Oktal, beachten Sie, dass zwischen Python2 und Python3 die Unterstützung für das 0110-Format eingestellt wurde und stattdessen 0o110 erforderlich ist. Dann portierten sie das 0o110-Parsing auf Python2 zurück, ohne das alte Format dort zu löschen, was es einfach machte, die neue, weniger fehleranfällige Syntax zu verwenden, ohne die Kompatibilität mit der alten Version zu beeinträchtigen. In Python2 hatte eine beträchtliche Anzahl von Python-Benutzern beim Einfügen von 0-aufgefüllten Dezimalzahlen versehentlich Oktalzahlen deklariert, was zu Verwirrung führte. (Häufiges Problem: längenaufgefüllte Seriennummern aus einer Teiledatenbank oder längenaufgefüllte Rechnungsnummern.) Ich habe deswegen tatsächlich einmal eine verwirrte halbe Stunde damit verbracht, herauszufinden, warum mein "offensichtlich korrekter" Komponententest fehlgeschlagen ist.

Auf der anderen Seite habe ich noch nie eine Unterstützung für Sprachkonstanten in einem beliebigen Radix benötigt. Vielleicht hat das jemand, aber das scheint ein Ablenkungsmanöver zu sein (und die Syntax, die dazu benötigt wird, klingt ziemlich hässlich).

Ein weiteres Beispiel, das mich gerade verbrannt hat, war das Definieren von Adressen in den eingebetteten Protokollen (I2C, SPI, CAN usw.), wo es oft eine Adresse gibt, die als binäre Konstante im verschobenen Datenblatt definiert ist und eine Art Lese-/Schreibbit hat als Teil des Wertes. Die Konvertierung in Hex fügt eine weitere Übersetzungsebene hinzu, die das menschliche Gehirn ausführen muss, also eine weitere Sache, die beim Debuggen in Frage gestellt werden muss.

Hallo @tapir , bitte lies meinen früheren Kommentar https://github.com/golang/go/issues/19308#issuecomment -352290337 insbesondere https://github.com/golang/go/wiki/NoPlusOne wie NoMeToo jetzt heißt.

Hier ist ein Gegenvorschlag, der eine beliebige Radix-Notation zu ungefähr den gleichen (oder weniger) Kosten ermöglicht: #28256 . I schlägt eine Notation vor, auf die ich in verschiedenen Diskussionen direkt oder indirekt angespielt, aber nie formell niedergeschrieben habe. Bitte kommentieren Sie dort für Meinungen.

Siehe #28493 (unabhängiger Vorschlag), in dem die Verwendung von _ als Trennzeichen zwischen Ziffern erörtert wird.

Wenn Sie diese alte Diskussion für Go 2 noch einmal besuchen, würde ich vorschlagen, sich gleichzeitig Oktal anzusehen. Offensichtlich können Sie die Notation 0123 nicht entfernen (aus Kompatibilitätsgründen - zumindest nicht ohne einen Verfallszeitraum), aber Sie können 0o123 gleichzeitig mit 0bXXX hinzufügen

Aber für sich allein wäre der binäre Vorschlag immer noch lohnenswert.

Würde strconv.ParseInt die Syntax 0b010 wenn base 0 ist?

@nathany Ja, wenn wir uns entscheiden, das 0b-Präfix in der Sprache zu unterstützen, sollten wir es auch in der Bibliothek unterstützen. Zum Beispiel verlässt sich der Compiler derzeit auf die SetString-Methode von math/big.Int, um Konstantenliterale in big.Ints umzuwandeln - also würde man erwarten, dass SetString (und Freunde wie strconv.ParseInt) auch 0b verstehen.

Vielleicht weniger offensichtlich ist, ob ParseInt auch _ Trennzeichen filtern soll, wenn wir dies zusammen mit #28493 akzeptieren. Es wäre einfach als separater Pfad (ersetzen Sie _ durch ` ) but for error handling (e.g.; do we allow _`, oder nicht) und Leistung, die wir möglicherweise in ParseInt (und allen anderen ParseXXX-Routinen für Zahlen) benötigen ).

Sollte es einen separaten Vorschlag/Problem für das oktale Literal 0o oder ist es besser, es mit diesem zusammenzufassen?

0o würde Swift und Rust entsprechen. Wir könnten ihre Gründe für die Bevorzugung dieser Syntax untersuchen.

Ein Grund, warum ich 0o gegenüber 0 besteht darin, Mehrdeutigkeiten mit strconv.ParseInt("012", 0, 64) zu vermeiden, wobei "012" Benutzereingaben sein könnten. Ich weiß jedoch nicht, ob dies in Go wie in anderen Sprachen ein großes Problem ist, da Atoi immer die Basis 10 verwendet und es keine Standardargumente in Go gibt, sodass der Programmierer explizit nach der Ableitung fragen muss die Basis aus dem Zeichenfolgenpräfix, indem Sie 0 für die Basis angeben.

Ich kann nicht sagen, dass ich jemals _ in einer geparsten Zeichenfolge verwenden musste. In der Tat weniger offensichtlich.

@nathany Ich würde ein separates Problem vorschlagen. Ich stimme zu, dass, wenn wir uns entscheiden, 0b zuzulassen, es sinnvoll sein könnte, auch 0o aus Konsistenzgründen zuzulassen (und dann möchten wir vielleicht, dass gofmt 0 -Präfix-Oktale automatisch umschreibt in 0o Präfix-Oktale, damit ersteres langsam aus der Codebasis entfernt werden kann). Bei diesem Vorschlag geht es jedoch um binäre Integer-Literale; belassen wir es dabei.

Meine ursprüngliche Frage wurde nicht beantwortet, daher habe ich den gesamten Thread noch einmal gelesen, um zu sehen, warum ein Thread
mit so vielen daumen hoch hat so wenig diskussion.

Bisher verlangt der Vorschlag aus folgenden Gründen binäre Literale:

andere Sprachen haben sie

Der Vorschlag geht akribisch darauf ein, wie andere Sprachen sie haben und wie andere sie gewohnt sind. War das schon mal ein Grund genug?

sie sind "leserlicher"

Ich bin nicht einverstanden. Sie sind ein heimtückisches Muster aus Einsen und Nullen, die ohne a . keine einfache Aussprache haben
Umstellung auf Basis16.

  • Du weißt es einfach

0b11110010 gegen 0xea. Sie müssen nicht einmal darüber nachdenken, was anvisiert wird, Sie müssen nur
wissen es, sobald Sie einen Blick darauf werfen.

_Das erste niederwertige Bit und das dritte niederwertige Bit und das fünfte niederwertige Bit sind ausgeschaltet, aber nicht der Rest. Und es gibt [zählt die Gesamtzahl der Bits zweimal, um sicherzustellen, dass die Zahl richtig ist] acht
Bits insgesamt._

Ich kenne das Muster und werde es mir wahrscheinlich für ein paar Sekunden merken. Wie ist das Wissen?
von Natur aus nützlich?

  • Gehen Sie gegen C++

Einige Argumente stellen ihren Nutzen falsch dar, vielleicht unbeabsichtigt. In einem besonderen Beispiel in
In diesem Thread wurde der folgende Ausschnitt gepostet, der go und c++ vergleicht.

constexpr uint_fast16_t FLAG_SPECIAL1  {0b0010000000000000};
constexpr uint_fast16_t FLAG_SPECIAL0  {0b0001000000000000};
constexpr uint_fast16_t RANGE_FLAG     {0b1111000000000000};
constexpr uint_fast16_t RANGE_FROM     {0b0000111111000000};
constexpr uint_fast16_t RANGE_TO       {0b0000000000111111};

This is my code example from C++17. In Go however, it will look like this:

const FlagSpecial1 uint16 = 8192
const FlagSpecial2 uint16 = 4096
const RangeFlag uint16 = 61440
const RangeFrom uint16 = 4032
const RangeTo uint16 = 63

Das Problem ist, dass C++ akribisch ausgerichtet ist, während Go unformatiert ist, keinen const Block enthält und fälschlicherweise Dezimal anstelle von Hex verwendet (das Sie nicht einfach in Binär umwandeln können, indem Sie jede Hex-Ziffer in vier Binär-Einsen aufteilen). .

const (
    FlagSpecial1 uint16 = 0x2000
    FlagSpecial2 uint16 = 0x1000
    RangeFlag    uint16 = 0xf000
    RangeFrom    uint16 = 0x0fc0
    RangeTo      uint16 = 0x003f
)

Protokollspezifikationen veröffentlichen manchmal Binärdateien

Ein weiteres Beispiel, das mich gerade verbrannt hat, war das Definieren von Adressen in den eingebetteten Protokollen
(I2C, SPI, > CAN, etc...) wobei oft eine Adresse als binäre Konstante im
Datenblatt verschoben > das eine Art Lese-/Schreibbit als Teil des Wertes hat. Konvertieren
sie zu hex fügt eine weitere Übersetzungsebene hinzu, die das menschliche Gehirn ausführen muss, also eine weitere
beim Debuggen zu hinterfragen.

Das Problem ist, dass das menschliche Gehirn dies überhaupt nicht für Sie tun sollte. |

Betrachten Sie Ihre Debugging-Erfahrung noch einmal. Werden binäre Integer-Literale in stderr oder ausgegeben
und grep für sie später? Werden Sie diese Zahlen mit Kollegen teilen, indem Sie jeweils 1 sagen
und 0 laut? Es ist wahrscheinlich, dass Sie sie eher in Hex ausgeben und übertragen, und wenn das wahr ist, ist es so
Es stimmt auch, dass der Quellcode diese Ziffern in Hex ausdrücken sollte, um die Notwendigkeit zu beseitigen
für das menschliche Gehirn (oder Programm), um noch mehr Arbeit für den Leser zu erledigen.

Viele Spezifikationen drücken 1010 , um einen Bitstrom zu bezeichnen, der aus diesen geordneten Zuständen besteht. Dies entspricht nicht der byteweisen Vorstellung von binären Integer-Literalen und wird sicherlich jemanden verbrennen, der erwartet
einen Bitstream-Reader zu implementieren. (Ich hätte lieber einen Bitstream-Reader in der Standardbibliothek implementiert, als binäre Integer-Literale zu unterstützen).

Ich bin heute auf diesen Mangel an Funktionen gestoßen. In meinem Beispielanwendungsfall verwende ich den ganzzahligen Wochentag
Feld eines Datums (0..6 bedeutet Sonntag..Samstag) und vergleicht es mit einer Präferenz-Bitmaske.
Da die Quelle der Ganzzahl programmgesteuert ist, definiere ich nicht für jeden Tag einen Satz von Konstanten
der Woche (mein Code hat keinen Grund, jemals speziell über SONNTAG zu sprechen), also 1 << 3 Syntax
ist hier nicht brauchbar. Ich möchte jedoch einen Standardwert für die Präferenz-Bitmaske, der wäre
vielleicht 0b0111110. Natürlich ist es einfach, diesen Standard als Dezimal (126) oder Hex (0x7e) zu schreiben, aber
es ist wesentlich klarer, es in binärer Form zu schreiben.

Ich würde die Wochentage als nicht exportierte Konstanten haben und die Maske erstellen, indem ich ihre Werte OR ing. Ich bin nicht der Meinung, dass binäre Integer-Literale in dieser Situation helfen würden, alles klarer zu machen.

@as Danke für deinen Kommentar. Es wurde aufgezeichnet.

Natürlich _brauchen_ wir keine binären Integer-Literale; wir haben eine ziemlich nahe Möglichkeit, solche Zahlen mit hexadezimalen Literalen auszudrücken (und darauf habe ich in meinem Blogbeitrag hingewiesen). Aber gleichzeitig scheinen sie für viele Programmierer ein Problem zu sein, und das können wir hier leicht beheben, ohne der Sprache viel Komplexität hinzuzufügen.

Vielleicht ist es besser, über dieses Thema nachzudenken, ob wir Go in dieser Hinsicht mit den meisten anderen Programmiersprachen auf Augenhöhe bringen und die Menge der ganzzahligen Literaldarstellungen vervollständigen wollen, indem wir alle relevanten Basen unterstützen (2, 8, 10, 16).

Dies ist eine Frage, die von der persönlichen Meinung über die Nützlichkeit binärer Literale getrennt und möglicherweise einfacher zu beantworten ist.

Änderung https://golang.org/cl/152338 erwähnt dieses Problem: spec: add binary integer literals (tentative)

Siehe https://golang.org/cl/152338 für die Spezifikationsänderungen, die für diesen Vorschlag relevant sind (ohne _-Trennzeichen in diesem ersten Schritt).

Änderung https://golang.org/cl/152377 erwähnt dieses Problem: spec: permit underscores for grouping in numeric literals (tentative)

Ich habe nach einem Benchmark für verschiedene Sortieralgos gesucht, bei denen Pseudozufalls auf 0xff & (i ^ 0xab) Wenn es 0b10101011 statt 0xab wäre, wäre es besser lesbar. Ich bin überrascht, dass es in Go keine binären Literale gibt, nicht einmal einen Vorschlag ...

@andrewmed Dies _ist_ der Vorschlag für binäre Integer-Literale.

Danke, verstanden

Wir haben einen kombinierten Vorschlag für #19308, #12711, #28493 und #29008 unter golang.org/design/19308-number-literals gepostet .

Beachten Sie, dass dies der erste Vorschlag ist, der dem im Blog-Beitrag beschriebenen Prozess folgt: Wir werden alles einsatzbereit haben und zu Beginn des Go 1.13-Zyklus (1. Februar) einchecken. Wir werden die nächsten drei Monate damit verbringen Features und das Einholen von Feedback basierend auf der tatsächlichen Nutzung, und dann zu Beginn des Release-Freeze (1. Mai) werden wir die "Startentscheidung" treffen, ob die Arbeit in Go 1.13 aufgenommen wird oder nicht.

Vielen Dank für Ihr Feedback und Ihre Hilfe bei der Verbesserung von Go.

Ursprünglich von @rsc vorgeschlagen : Es könnte ratsam sein, 0X für hexadezimal abzulehnen (aber immer noch zu unterstützen) und dann 0B (unnötig) und 0O (unnötig, verwirrend und schwer zu lesen) nicht hinzuzufügen.

@robpike ...und lassen Sie gofmt anfangen, 0X in 0x zu ändern.

@josharian , ja, ich habe das auch für oktale Zahlen (0644 -> 0o644) angesprochen, aber zumindest im oktalen Fall konnten wir es nur in goimports wirklich tun, wo wir die von go.mod deklarierte Mindestsprachversion für die kennen würden Code in diesem Modul.

Aber für 0X -> 0x könnte es in gofmt gemacht werden, ja.

Ich habe keine starken Gefühle für 0B vs 0b und 0O vs 0o (viele Code-Editoren schreiben eine Null mit einem Schrägstrich, die anders aussieht als ein großes O; persönlich verwende ich immer Kleinbuchstaben).

Aber der Hauptpunkt beim Hinzufügen dieser neuen Formate besteht darin, mit anderen Sprachen kompatibel zu sein und den Leuten, die aus solchen Sprachen kommen, die Mühe zu nehmen und vielleicht Code von woanders zu übersetzen. Es würde diesen Zweck zunichte machen, wenn besagte Personen oder Code in diesen Präfixen Großbuchstaben verwenden und Go diese Literale schließlich nicht verarbeiten könnte.

Ich stelle auch fest, dass es eine kleine Inkonsistenz mit dem Exponenten geben wird, wo wir E und e (und neu P und p) zulassen.

Kurz gesagt, obwohl ich das Gefühl voll und ganz unterstütze, scheint das Verbieten von Großbuchstaben 0B wie ein grundloser Unterschied zu sein, der den Leuten, die es gewohnt sind, 0b sowieso kleingeschrieben zu haben, sowieso nicht hilft (was meiner Meinung nach die Mehrheit ist) und den anderen schadet.

Auf der anderen Seite scheint es eine gute Idee zu sein, dass gofmt die Änderung automatisch (oder vielleicht mit -s) vornimmt.

Als Embedded-Entwickler, der viel mit einzelnen Bits und Bitmasken arbeitet, wären binäre Literale eine willkommene Abwechslung. Ich habe sie vor kurzem in (GC)C entdeckt und war angenehm überrascht.
natürlich kann so ziemlich jeder ziemlich schnell 0x1 , 0x80 und 0x8000 verstehen. aber etwas wie 0x1c lässt dich innehalten. (7 << 2) ist natürlich etwas besser 0b00011100 ist einfach besser lesbar und vermittelt die Bedeutung - drei zusammenhängende Bits 2 Positionen links - deutlicher.

Änderung https://golang.org/cl/157677 erwähnt dieses Problem: cmd/compile: accept new Go2 number literals

Änderung https://golang.org/cl/159997 erwähnt dieses Problem: go/scanner: accept new Go2 number literals

Änderung https://golang.org/cl/160018 erwähnt dieses Problem: cmd/gofmt: test that Go 2 number literals can be formatted

Änderung https://golang.org/cl/160239 erwähnt dieses Problem: go/constant: accept new Go2 number literals

Änderung https://golang.org/cl/160240 erwähnt dieses Problem: go/types: add tests for new Go 2 number literals

Änderung https://golang.org/cl/160247 erwähnt dieses Problem: fmt: scan new number syntax

Änderung https://golang.org/cl/160250 erwähnt dieses Problem: math/big: add %#b and %O integer formats

Änderung https://golang.org/cl/160248 erwähnt dieses Problem: text/template: accept new number syntax

Änderung https://golang.org/cl/160246 erwähnt dieses Problem: fmt: format 0b, 0o prefixes in %#b and %O

Änderung https://golang.org/cl/160244 erwähnt dieses Problem: strconv: add 0b, 0o integer prefixes in ParseInt, ParseUint

Änderung https://golang.org/cl/160184 erwähnt dieses Problem: cmd/gofmt: normalize number prefixes and exponents

Änderung https://golang.org/cl/160478 erwähnt dieses Problem: design/19308-number-literals: add note about gofmt

Zur Erinnerung haben wir in unserem Blog-Beitrag blog.golang.org/go2-here-we-come einen neuen Prozess für diese Go 2-bezogenen Sprachänderungen eingeführt. Wir werden einen Vorschlag vorläufig annehmen, Landwechsel zu Beginn eines Zyklus, Erfahrungen damit sammeln und dann drei Monate später beim Einfrieren die endgültige Annahmeentscheidung treffen. Für Go 1.13 würde dies bedeuten, eine Änderung vorzunehmen, wenn der Baum im Februar geöffnet wird, und die endgültige Entscheidung zu treffen, wenn der Baum im Mai einfriert.

Wir werden diesen Vorschlag für Go 1.13 vorläufig annehmen und planen, seine Implementierung zu landen, wenn der Baum geöffnet wird. Der Ausgabestatus für "vorläufige Annahme" wird als Angebot angenommen markiert, aber offen gelassen und als Meilenstein für die Go-Version (hier Go1.13) angegeben. Beim Einfrieren werden wir das Thema erneut aufgreifen und es schließen, wenn es endgültig akzeptiert wird.

Änderung https://golang.org/cl/161098 erwähnt dieses Problem: spec: document new Go2 number literals

Änderung https://golang.org/cl/161199 erwähnt dieses Problem: text/scanner: accept new Go2 number literals

Änderung https://golang.org/cl/163079 erwähnt dieses Problem: text/scanner: don't liberally consume (invalid) floats or underbars

Änderung https://golang.org/cl/173663 erwähnt dieses Problem: unicode/utf8: use binary literals

Änderung https://golang.org/cl/174897 erwähnt dieses Problem: cmd/compile: disable Go1.13 language features for -lang=go1.12 and below

Zur Erinnerung haben wir in unserem Blog-Beitrag blog.golang.org/go2-here-we-come einen neuen Prozess für diese Go 2-bezogenen Sprachänderungen eingeführt. Der Entwicklungszyklus von Go 1.13 ist nun vorbei und es ist Zeit für die endgültige Entscheidung.

Das Feedback zu den Änderungen des Go 2-Zahlenbuchs war stark positiv, mit sehr wenigen negativen Stimmen. Diese Änderungen modernisieren und harmonisieren die Zahlenliteral-Syntax von Go, ohne die Sprache wesentlich zu komplexieren: Es gibt jetzt eine einheitliche Präfix-Notation für die drei gängigen nicht-dezimalen Zahlenbasen, die der in anderen modernen Programmiersprachen verwendeten Notation entspricht. Die Einführung von hexadezimalen Gleitkomma-Literalen adressiert einen Schwachpunkt für Leute, die sich mit numerischem Code beschäftigen. Das Suffix „i“ kann jetzt mit jedem (nicht imaginären) Zahlenliteral verwendet werden, um auf einheitliche Weise eine imaginäre Konstante zu erzeugen. Und schließlich können Unterstriche verwendet werden, um längere Literale zur besseren Lesbarkeit in Zifferngruppen aufzuteilen.

Vorschlag für Go 1.13 angenommen. Schließt, weil die Änderungen gelandet sind.

- rsc für die Angebotsprüfung

Änderung https://golang.org/cl/189718 erwähnt dieses Problem: compiler: support new numeric literal syntax

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen