Pegjs: Bieten Sie eine prägnante Möglichkeit, einen einzelnen Rückgabewert aus einer Sequenz anzugeben

Erstellt am 29. Jan. 2014  ·  21Kommentare  ·  Quelle: pegjs/pegjs

Das ist bei mir ziemlich üblich. Ich möchte nur den relevanten Teil einer Sequenz im Init-Label zurückgeben. In diesem Fall nur die AssignmentExpression.

pattern:Pattern init:(_ "=" _ a:AssignmentExpression {return a})?

Ich empfehle Ihnen, einen @-Ausdruck hinzuzufügen, der nur den folgenden Ausdruck aus der Sequenz zurückgibt. Das obige Beispiel würde also so aussehen:

pattern:Pattern init:(_ "=" _ @AssignmentExpression)?

Verwandte Themen:

  • #427 Rückgabe des Übereinstimmungsergebnisses eines bestimmten Ausdrucks in einer Regel ohne Aktion zulassen
  • #545 Einfache Syntaxerweiterungen zum Kürzen von Grammatiken
feature

Hilfreichster Kommentar

Wurde dies bereits für das Dev-Tag auf npm freigegeben?

https://www.npmjs.com/package/pegjs/v/0.11.0-dev.325

Alle 21 Kommentare

Ich stimme zu, dass dies ein häufiges Problem ist. Aber ich bin mir nicht sicher, ob es sich lohnt zu lösen. Mit anderen Worten, ich bin mir nicht sicher, ob es oft genug auftritt und ob es genug Schmerzen verursacht, um eine Komplexität von PEG.js durch die Implementierung einer Lösung zu rechtfertigen, was auch immer das wäre.

Ich werde dieses Problem offen lassen und es nach 1.0.0 zur Prüfung vormerken.

Einverstanden. Ich würde das wirklich gerne in 1.0 sehen. Von der @-Syntax bin ich jedoch nicht so begeistert. IMHO wäre eine bessere Idee, dies zu tun: Wenn es nur ein einziges Label der "obersten Ebene" gibt, dann geben Sie dieses Label implizit zurück. Also statt:

rule = space* a:(text space+ otherText)+ newLine* { return a; }

Du erhältst:

rule = space* a:(text space+ otherText)+ newLine*

Und wenn das Etikett nicht besonders aussagekräftig ist, erlauben Sie auch dies:

rule = space* :(text space+ otherText)+ newLine*

Überspringen Sie also den Labelnamen ganz.

@mulderr Ich denke, der @-Operator ist besser, da ich implizit bedeutet, dass ich, wenn ich den Code von jemand anderem lese, der diese Funktion verwendet, ziemlich viel googeln muss, bevor ich erkenne, was er dort getan hat. Im Gegensatz dazu würde mir die Verwendung eines expliziten Operators ermöglichen, die Dokumentation schnell zu durchsuchen.

+1 für @ - Dies kommt in meinem Code häufig vor.

+1 für eine kurze Möglichkeit, dies zu tun.

Es scheint , wie dieser Schmerz zu , dass die ausführlichen ähnlich ist function Syntax in JS, die ES6 Adressen der mit Pfeilfunktionen . Vielleicht könnte hier etwas Ähnliches verwendet werden? Etwas wie:

rule = (space* a:(text space+ otherText) newLine*) => a

Mir scheint, dass dies ziemlich flexibel und immer noch explizit ist (a la @wildeyes ' Anliegen) und sich weniger nach Komplexität anfühlt, da es sich sowohl in der Syntax als auch in der Implementierung auf das zugrunde liegende JS bezieht ...

Ich habe mir sowas ein bisschen vorgestellt:

additive = left:multiplicative "+" right:additive {= left + right; }

Wo ein = (Sie können die Wahl des Zeichens frei diskutieren) als erstes Nicht-Leerzeichen eines Blocks in ein return .

Dies würde auch für vollständige Ausdrücke funktionieren und sollte mit einem Transformationsdurchgang möglich sein.

Irgendwelche Neuigkeiten? Warum nicht additive = left:multiplicative "+" right:additive { => left + right } ?

Es würde sich sicherlich intuitiv anfühlen, wenn man bedenkt, wie die Pfeilfunktionen jetzt funktionieren ( (left, right) => left + right ).

Es gibt tatsächlich einige Beispiele für Stellen in Ihrer parser.pegjs-Datei, die durch diese Funktion verbessert werden könnten.

Zum Beispiel:

  = head:ActionExpression tail:(__ "/" __ ActionExpression)* {
      return tail.length > 0
        ? {
            type: "choice",
            alternatives: buildList(head, tail, 3),
            location: location()
          }
        : head;
    }

Ist aufgrund der magischen Zahl 3 im buildList-Aufruf fragil, die nicht intuitiv mit der Position Ihres ActionExpression in der Sequenz verknüpft ist. Die Funktion buildList selbst wird durch die Kombination zweier verschiedener Operationen kompliziert. Durch die Verwendung des @-Ausdrucks und der Spread-Syntax von es6 wird dies sauberer:

  = head:ActionExpression tail:(__ "/" __ @ActionExpression)* {
      return tail.length > 0
        ? {
            type: "choice",
            alternatives: [head, ...tail],
            location: location()
          }
        : head;
    }

Da dies so ziemlich nur syntaktischer Zucker ist, konnte ich diese Funktion zu Ihrem Parser hinzufügen, indem ich einfach den ActionExpression in parser.pegjs änderte

  = ExtractSequenceExpression
  / expression:SequenceExpression code:(__ CodeBlock)? {
      return code !== null
        ? {
            type: "action",
            expression: expression,
            code: code[1],
            location: location()
          }
        : expression;
    }

ExtractExpression
  = "@" __ expression:PrefixedExpression {
      return {
        type: "labeled",
        label: "value",
        expression: expression,
        location: location()
      };
    }

ExtractSequenceExpression
  = head:(__ PrefixedExpression)* _ extract:ExtractExpression tail:(__ PrefixedExpression)* {
      return {
        type: "action",
        expression: {
          type: "sequence",
          elements: extractList(head, 1).concat(extract, extractList(tail, 1)),
          location: location()
        },
        code: "return value;",
        location: location()
      }
    }

Ich habe ein Wesentliches eingecheckt, das zeigt, wie die parser.pegjs durch die Verwendung der @-Notation vereinfacht werden würde.

Die Funktionen ExtractOptional, ExtractList und buildList wurden vollständig entfernt, da die @-Notation das Extrahieren von gewünschten Werten aus einer Sequenz trivial macht.

https://gist.github.com/krisnye/a6c2aac94ffc0e222754c52d69e44b83

@krisnye So würde es aussehen, wenn es noch mehr

https://github.com/polkovnikov-ph/newpeg/blob/master/parse.np

Ich überlege, eine Kombination aus :: und # für diese Syntaxfunktion zu verwenden (siehe

  • :: der Bindungsoperator
  • # der Erweiterungsoperator
// this is imported into grammar
class List extends Array {
  constructor() { this.isList = true; }
}

// grammar
number = _ ::value+ _
value = ::int #(_ "," _ ::int)* { return new List(); }
int = $[0-9]+
_ = [ \t]*
  • Auf der Wurzelsequenz einer Regel gibt :: das Ergebnis des Ausdrucks als Regelergebnis zurück
  • In einer verschachtelten Sequenz gibt :: das Ergebnis des verschachtelten Ausdrucks als Sequenzergebnis zurück
  • Wenn mehr als ein :: verwendet wird, wird das Ergebnis der markierten Ausdrücke als Array zurückgegeben
  • Wenn # für eine verschachtelte Sequenz verwendet wird, die :: , werden die Ergebnisse in das Array des übergeordneten Elements übertragen
  • Wenn die Regel einen Codeblock zusammen mit :: / # , führen Sie sie zuerst aus und verwenden Sie dann die Methode der Ergebnisse push

Nach diesen Regeln würde die Übergabe von 09 , 55, 7 an den generierten Parser des obigen Beispiels ergeben:

result = [
    isList: true
    0: "09"
    1: "55"
    2: "7"
]

result instanceof Array # true in ES2015+ enviroments
result instanceof List # true

Auf der Wurzelsequenz einer Regel gibt :: das Ergebnis des Ausdrucks als Regelergebnis zurück
In einer verschachtelten Sequenz gibt :: das Ergebnis des verschachtelten Ausdrucks als Sequenzergebnis zurück

Warum sind diese getrennt? Warum nicht einfach " :: auf einer Sequenz ergibt das Ergebnis des Arguments Ergebnis der Sequenz"?

Bei mehr als einem :: wird das Ergebnis der markierten Ausdrücke als Array zurückgegeben.

Das ist eine schlechte Idee. In diesem Fall würde es eher aussteigen. Es macht keinen Sinn, Werte mehrerer Typen in einem Array zusammenzufassen. (Das wäre ein Tupel, aber sie sind in JS ziemlich nutzlos.)

Wenn # für eine Sequenz verwendet wird, werden die Ergebnisse Array#concat'ed in das Array des übergeordneten Elements

Das ist jetzt eine schreckliche Idee. Dies ist offensichtlich ein Fehler, um überflüssige { return xs.push(x), xs } loszuwerden. Es macht keinen Sinn, einen solchen Sonderfall zu erstellen, da er mit parametrisierten Regeln generisch gelöst werden könnte. Es gibt nicht viele Einzelzeichenfolgen für Operatoren, und wir sollten sie nicht verschwenden.

Wenn die Regel zusammen mit ::/# einen Codeblock enthält, führen Sie ihn zuerst aus und verwenden Sie dann die Push-Methode für Ergebnisse

Also sollte f = ::"a" { return "b" } ["a", "b"] als Ergebnis haben?

vorbei am 09. 55: 7 für den generierten Parser des obigen Beispiels würde ergeben:

Es würde nicht, es wird kein . oder : erwähnt. Ich sehe auch nicht, wie das beschriebene Verhalten zu dem Ergebnis führen würde.

Zahl = _ ::Wert+ _

Außerdem sollte _ nicht so verwendet werden. Es geht entweder rechts oder links vom Token, die Seite wird einmal für die Grammatik ausgewählt. Falls es rechts ist, sollte die Hauptregel auch mit _ und umgekehrt.

start = _ value
value = ::int #("," _ ::int)* { return new List(); }
number = ::$[0-9]+ _
_ = [ \t]*

Ein Beispiel für im JavaScript-Beispiel implementierte Klassen (nicht als echte Implementierung gedacht):

ClassMethod
  = head:FunctionHead __ params:FunctionParameters __ body:FunctionBody {
      return {
        type: "method",
        name: head[ 1 ],
        modifiers: head[ 0 ],
        params: params,
        body: body
      };
    }

// `::` inside the zero_or_more "( ... )*" builds an array as we want,
// so this rule returns `[FunctionModifier[], Identifier]` as expected
MethodHead = (::MethodModifier __)* ("function" __)? ::Identifier

// https://github.com/tc39/proposal-class-fields#private-fields
MethodModifier
  = "#"
  / "static"
  / "async"

FunctionParameters
  = "(" __ head:FunctionParam tail:(__ "," __ ::FunctionParam)* __ ")" {
      // due to `::`, tail is `FunctionParam[]` instead of `[__, "", __, FunctionParam][]`
      return [ head ].concat( tail );
    }
    / "(" __ ")" { return []; }

FunctionParam
  = name:Identifier value:(__ "=" __ ::Expression)? {
      return { name, value };
    }

FunctionBody = "{" __ ::SourceElements? __ "}"

Warum sind diese getrennt? Warum nicht nur :: auf einer Sequenz das Ergebnis des Arguments Ergebnis der Sequenz"?

Ist das nicht dasselbe? Ich habe es nur klarer gemacht, damit das Ergebnis verschiedener Anwendungsfälle wie MethodHead , FunctionParam und FunctionBody leicht zu verstehen ist.

Es macht keinen Sinn, Werte mehrerer Typen in einem Array zusammenzufassen. (Das wäre ein Tupel, aber sie sind in JS ziemlich nutzlos.)

Beim Erstellen eines AST (das häufigste Ergebnis eines generierten Parsers) würde es meiner Meinung nach Anwendungsfälle wie MethodHead vereinfachen, anstatt zu schreiben:

MethodHead
  = modifiers:(::MethodModifier __)* ("function" __)? name:Identifier {
      return [ modifiers, name ];
    }

Nachdem ich es jedoch gründlicher durchgedacht habe, eröffnet es, obwohl es den Anwendungsfall vereinfacht, auch die Möglichkeit, dass der Entwickler einen Fehler macht (entweder in der Art und Weise, wie er seine Grammatik implementiert oder wie die Ergebnisse durch Aktionen gehandhabt werden), daher denke ich, dies zu sagen Use Case hinter einer Option wie multipleSingleReturns (Standard: false ) wäre hier die beste Vorgehensweise (wenn diese Funktion implementiert wird).

Wenn # für eine Sequenz verwendet wird, werden die Ergebnisse Array#concat'ed in das Array des übergeordneten Elements

Das ist jetzt eine schreckliche Idee. Dies ist offensichtlich ein Fehler, um Fremdkörper loszuwerden { return xs.push(x), xs }

Es hilft auch in den häufigeren Anwendungsfällen wie FunctionParameters wo es schöner wäre zu schreiben:

// should always return `FunctionParam[]`
FunctionParameters
  = "(" __ ::FunctionParam #(__ "," __ ::FunctionParam)* __ ")"
  / "(" __ ")" { return []; }

es könnte generisch mit parametrisierten Regeln gelöst werden

Ich denke, dass ich einzelne Rückgabewerte vor parametrisierten Regeln implementieren sollte, da ich mir immer noch nicht sicher bin, wie ich mit den späteren fortfahren soll (ich verwende gerne Vorlagen, aber die Verwendung von rule < .., .. > = .. scheint viel Lärm zu machen die PEG.js-Grammatik, also überlege ich mir eine geringfügige Syntaxänderung, damit sie besser passt), aber das ist ein separates Problem.

Es gibt nicht viele Einzelzeichenfolgen für Operatoren, und wir sollten sie nicht verschwenden.

Das stimmt, aber wenn wir sie nicht verwenden, wenn der Anlass so ist, dann ist das genauso schlimm.

Ich dachte daran, # für diesen Anwendungsfall zu verwenden, nachdem ich mich daran erinnert hatte, dass es in einigen Sprachen, die Präprozessdirektiven implementieren, als Erweiterungsoperator verwendet wird, und das ist im Wesentlichen das, was dieser Anwendungsfall hier behandelt.

Also sollte f = ::"a" { return "b" } ["a", "b"] als Ergebnis haben?

Nein, da der Codeblock vom Parser erwartet wird, dass er ein Array-ähnliches Objekt zurückgibt, das eine push Methode enthält (also f = ::"a" { return [ "b" ] } [ "b", "a" ] als Ergebnis pushSingleReturns steckt? Wenn diese Option false (Standard) ist, würde ein Codeblock nach einer Sequenz, die einzelne Rückgabewerte enthält, einen Fehler auslösen.

vorbei am 09. 55: 7 für den generierten Parser des obigen Beispiels würde ergeben:

Es würde nicht, es wird kein . oder : erwähnt.

Entschuldigung, das war ein Fehler, der beim Umschreiben des gegebenen Beispiels vergessen wurde.

Außerdem sollte _ nicht so verwendet werden. Es geht entweder rechts oder links vom Token, die Seite wird einmal für die Grammatik ausgewählt. Falls es rechts ist, sollte die Hauptregel auch mit _ und umgekehrt.

Ich denke, das ist wirklich nur eine Frage der Präferenz :smile:, obwohl ich denke, es wäre einfacher gewesen, dieses Beispiel zu verstehen:

number = _ ::value+ EOS
...
EOS = !.

Ich sehe auch nicht, wie das beschriebene Verhalten zu dem Ergebnis führen würde.

Hilft dieser aktualisierte Kommentar zu verstehen, was ich sagen möchte, und wenn nicht, was verstehen Sie nicht?

Ich stimme @polkovnikov-ph zu, dass die angebotenen Änderungen nach Orten äußerst nicht offensichtlich sind und nur eine zusätzliche Fehlerquelle darstellen.

Wenn # für eine Sequenz verwendet wird, werden die Ergebnisse Array#concat'ed in das Array des übergeordneten Elements

Was soll in der Grammatik start = #('a') ? Soweit ich verstehe, dachte er, wie Syntax Zucker für Arrays glätten? Ich glaube nicht, dass dieser Operator notwendig ist. Für die offensichtlichste Verwendung – Ausdrücke von Mitgliedslisten mit Trennzeichen – ist die spezielle Syntax besser zu erstellen (siehe #30 und meine Abzweigung, https://github.com/Mingun/pegjs/commit/db4b2b102982a53dbed1f579477c85c06f8b92e6).

Wenn die Regel zusammen mit ::/# einen Codeblock enthält, führen Sie ihn zuerst aus und verwenden Sie dann die Push-Methode für Ergebnisse

Extrem unscheinbares Verhalten. Aktionen in der Grammatikquelle befinden sich nach expression und werden normalerweise nach dem Parsen von expression aufgerufen. Und plötzlich werden sie irgendwie vor dem Parsen aufgerufen. Wie sollen sich Etiketten verhalten?

Die verbleibenden 3 Punkte haben Sie so beschrieben, dass ihr klarer Sinn zu entkommen begann. Wie richtig hat @polkovnikov-ph notiert, warum in der Beschreibung der erste und der zweite Fall getrennt wurden? Es dürfen nur zwei einfache Regeln ausgeführt werden:

  1. :: (ehrlich gesagt mag ich eine Auswahl dieses Zeichens nicht, zu laut) vor Ausdrücken führt dazu, dass aus den sequence Knotenelementen, die mit diesem Zeichen gekennzeichnet sind, zurückkehren
  2. Wenn in der Sequenz nur ein solches Element vorhanden ist, wird dessen Ergebnis zurückgegeben, andernfalls wird das Array der Ergebnisse zurückgegeben

Beispiele:

start =   'a' 'b'   'c'; // => ['a', 'b', 'c']
start = ::'a' 'b'   'c'; // => 'a'
start = ::'a' 'b' ::'c'; // => ['a', 'c']

Das große Beispiel beschreibt genau das, was ich von :: erwarten würde, und beschreibt keine dubiosen Anwendungsfälle ( # , mehrere :: ).

Ist das nicht dasselbe?

Das ist, was ich gefragt habe. Die allgemeine Beschreibung ist in der Regel nützlicher, da sie dem Leser die Gewissheit gibt, dass es sich wirklich um dasselbe handelt. Vielen Dank für die Klarstellung. :)

meiner Meinung nach würde es Anwendungsfälle wie MethodHead vereinfachen

Aber warum nicht stattdessen ein Objekt erstellen? Es gibt modifiers: und name: in der Notation, belassen Sie sie im resultierenden JS-Objekt, und das wird cool.

es eröffnet auch die Möglichkeit, dass der Entwickler einen Fehler macht (entweder in der Art und Weise, wie er seine Grammatik implementiert oder wie die Ergebnisse durch Aktionen gehandhabt werden).

Anfangs wollte ich darüber schreiben, entschied dann aber, dass ich nicht genug harte Argumente habe. Ich würde lieber nicht mehrere :: auf derselben Sequenzebene zulassen (auch nicht mit einem Flag).

Es hilft auch in den häufigeren Anwendungsfällen wie FunctionParameters, wo es schöner wäre zu schreiben:

Aber das ist dasselbe. Eine wirklich schöne Syntax wäre inter(FunctionParam, "," __) , mit

inter a b = x:a xs:(b ::a)* { return xs.unshift(x), xs; }

rule < .., .. > = .. scheint der PEG.js-Grammatik viel Rauschen hinzuzufügen

Die Leute erwarten, dass <...> für Typen verwendet wird, während in diesem Fall Argumente keine Typen sind. Der beste Weg ist der Haskell-Weg ohne zusätzliche Zeichen (siehe inter oben). Ich bin mir nicht sicher, wie dies in der PEG.js-Grammatik mit weggelassenen ; interagiert. Es kann vorkommen, dass f a b = ... (teilweise) in die vorherige Zeile aufgenommen wird.

als Erweiterungsoperator in einigen Sprachen verwendet, die Vorverarbeitungsdirektiven implementieren

Ja, aber ich würde es lieber intelligent verwenden. Anstelle der vorgeschlagenen push Aktion für Arrays würde ich sie als Object.assign Aktion für Objekte verwenden oder sogar als etwas, das mit einer leeren Zeichenfolge übereinstimmt ( eps ), aber zurückgibt seine Argumentation. Damit zum Beispiel

f = type:#"ident" name:$([a-z]i [a-z0-9_]i+)

würde {type: "ident", name: "abc"} für die Eingabe "abc" .

Nein, da der Codeblock vom Parser erwartet wird, dass er ein Array-ähnliches Objekt zurückgibt, das eine Push-Methode enthält (also f = ::"a" { return [ "b" ] } return [ "b", " a" ] als Ergebnis),

O_O

Ich denke, das ist wirklich nur eine Frage der Präferenz

Nicht nur das, sondern auch die Leistung. Wenn jedes Token auf beiden Seiten _ , stimmen Leerzeichenfolgen nur mit nachfolgenden Zeichen überein, während vorangehende _ mit nichts übereinstimmen. Zusätzliche Anrufe bei parse$_ nehmen etwas mehr Zeit in Anspruch. Außerdem ist der Code länger, weil er doppelt so viele _ s hat.

@Mingun Ich denke, @futagoza erforscht den

Die Hauptsache ist, nicht zu fragen "warum", sondern zu sagen "nein! nicht so!"

image

f = type:#"ident" name:$([a-z]i [a-z0-9_]i+) würde {type: "ident", name: "abc"} für die Eingabe "abc" .

Bitte nein, haha. Diese Syntax ist _wayyy_ zu magisch.

Ich denke, der ursprünglich vorgeschlagene Operator @ ist so wie er ist perfekt . So oft stoße ich auf das Sequenzproblem:

sequence
    = first:element rest:(whitespace next:element {return next;})*
    {
        return [first].concat(rest);
    }
    ;

_Such_ es ist mühsam, immer wieder zu tippen, besonders wenn sie komplexer sind.

Mit dem Operator @ wird das Obige jedoch einfach:

sequence = first:element rest:(whitespace @element)* { return [first].concat(rest); };

und entweder mit https://github.com/pegjs/pegjs/issues/235#issuecomment -66915879 oder https://github.com/pegjs/pegjs/issues/235#issuecomment -67544080 wird das weiter reduziert auf:

sequence = first:element rest:(whitespace @element)* => [first].concat(rest);
/* or */
sequence = first:element rest:(whitespace @element)* {=[first].concat(rest)};

... die erste davon mag ich sehr.

Dies scheint eine abwärtskompatible Änderung zu sein, die einfach zu erreichen wäre (anscheinend hat es jemand bereits getan).

Wenn ich mich nicht irre, könnte es sich sogar um eine kleine Beule handeln. Könnte für 0.11.0 @futagoza etwas zum Nachdenken sein.

Habe dies gerade zum Master hinzugefügt. Ich hatte vor, :: für Mehrfachzupfen und @ für Einzelzupfen zu verwenden, aber die Verwendung von :: mit Etiketten sah wirklich hässlich und verwirrend aus, also hängte diese Idee auf 🙄

Ich habe vor einiger Zeit damit begonnen, dies selbst zu implementieren, aber bis jetzt fallen gelassen (wo ich stattdessen #579 machen sollte 😆) und den Bytecode-Generator auf Minguns Implementierung basiert (https://github.com/Mingun/pegjs/commit/1c1c852bae91868eaa90d9bd9f7e4f722aa6435e )

Sie können es hier ausprobieren: https://pegjs.org/development/try (der Online-Editor, aber mit PEG 0.11.0-dev)

Heilige Turnaround-Zeit, Batman. Tolle Arbeit dev Tag

Für alle, die es mit einer grundlegenden Grammatik versuchen möchten, setzen Sie diesen Welpen dort ein und geben Sie ihm eine Eingabe wie "abcd" .

foo
    = '"' @$bar '"'
    ;

bar
    = [abcd]*
    ;

Wurde dies bereits für das Dev-Tag auf npm freigegeben?

https://www.npmjs.com/package/pegjs/v/0.11.0-dev.325

Hi, dies ist ein weiteres Problem, das einfach verschwindet, wenn wir es6 haben, und wir brauchen diese Zeichen für andere Dinge, die seitdem zu es6 hinzugefügt wurden. Das Hinzufügen von Operatoren für Dinge, die Sie bereits tun können, ist sehr kontraproduktiv.

Dieses Ticket wurde zusammengeführt

pattern:Pattern init:(_ "=" _ <strong i="7">@a</strong>:AssignmentExpression)?

Das Gleiche in es6, das jeder von Natur aus verstehen wird und das kostenlos zur Verfügung steht, wenn die anderen Teile des Parsers fertig sind, ist

pattern:Pattern init:(_ "=" _ a:AssignmentExpression)? => a

Problematischerweise scheint diese Pluck-Implementierung beim Testen fehlerhaft zu sein, und natürlich ist dies als geschlossen gekennzeichnet, da dies in einem Zweig behoben ist, der nie veröffentlicht wird

Bitte öffnen Sie dieses Problem erneut, @futagoza , bis dies in einer veröffentlichten Version behoben ist

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen