Godot: Array-Slicing für GDScript

Erstellt am 19. Mai 2016  ·  36Kommentare  ·  Quelle: godotengine/godot

wäre schön, wenn wir die pythonische Slice-Funktion wie verwenden könnten

array[2:4]
array[2:]
array[:-1]

oder sogar erweitertes Schneiden mit Schritt

array[::2]
array[::-1]
feature proposal pr welcome gdscript

Hilfreichster Kommentar

imho Python-Syntax mit: ist bequemer - weniger Zeichen und kompakter

+1. Und weniger verwirrend. Wir sind Python-ähnlich, also importieren wir keine Verhaltensweisen aus allen anderen Sprachen der Welt, sonst wird GDScript wirklich inkonsistent.

Alle 36 Kommentare

Beachten Sie, dass dies mit range und dem Verständnis aus #4716 einfach zu bewerkstelligen ist:

var result = array[from:to:step]
# Is the same as:
var result = (array[i] for i in range(from,to,step))

Um auch hier die CoffeeScript-Syntax einzugeben:

x = array[from...to]

Wir könnten dies anpassen, um die Schrittgröße zu unterstützen (da dies nicht der Fall ist):

x = array[from..step..to]
# or
x = array[from...to:step]

imho Python-Syntax mit: ist bequemer - weniger Zeichen und kompakter

imho Python-Syntax mit: ist bequemer - weniger Zeichen und kompakter

+1. Und weniger verwirrend. Wir sind Python-ähnlich, also importieren wir keine Verhaltensweisen aus allen anderen Sprachen der Welt, sonst wird GDScript wirklich inkonsistent.

D-Syntax ($ ist die Größe des Arrays):

array[2..4]
array[2..$]
array[$-1..$]

Nur als Referenz. Ich stimme zu, dass Python besser zu GDScript passt: P

Ich bin bereit, an diesem zu arbeiten.

Als ersten Schritt bereite ich eine PR vor, die eine negative Indexierung hinzufügt. (Wenn wir array[:-1] zulassen, sollten wir auch array[-1] zulassen.)

Was ist mit der Zuweisung zu Array-Slices? Gibt es Anwendungsfälle?

Ich bin zuversichtlich, dass ich den Code zur Unterstützung bekommen kann, aber wenn es keine Anwendungsfälle gibt, mache ich mir vielleicht keine Sorgen.

Ich denke, eine Einschränkung, die wir machen müssen, ist, dass die Ersatzwerte dieselbe Größe haben müssen (was Python auch bei Array-ähnlichen Strukturen mit fester Größe wie Bytes erzwingt).

Mit anderen Worten, Folgendes sollte funktionieren:

var a = range(10)
a[2:5] = [10, 11, 12]
print(a) #[0, 1, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9]

Folgendes könnte:

a = range(10)
a[1::2] = [10, 11, 12, 13, 14]
print(a) # [0, 10, 2, 11, 4, 12, 6, 13, 8, 14]

Aber das wird höchstwahrscheinlich nicht:

a = range(10)
a[2:5] = [10]
print(a) # [0, 1, 10, 5, 6, 7, 8, 9]

Meinungen?

Nur fürs Protokoll, ich arbeite noch daran. Ich könnte in der nächsten Woche eine PR fertig haben, aber es kann länger dauern.

@brakhane Niemand hat es sehr eilig - lass dir Zeit :)

siehe #5701 und #5765
Ich habe DVector- und ByteArray-Bindungen eine einfache 2-Argument-Slice-Operation hinzugefügt, die mit einigen zukünftigen Bindungen auf jeden der GDSript-Array-Typen auf niedriger Ebene (IntArray, StringArray usw.) angewendet werden kann. Code ist noch nicht da, um mit -1 umzugehen. Mir ist gerade aufgefallen, dass ich diese Bequemlichkeit gerade weggelassen habe.

Ich denke, dies sollte für 3.0 implementiert werden, derzeit haben wir nur die Methode subarray(from, to) für PoolByteArray implementiert, aber nicht für andere eingebaute Typen, daher ist sie sehr inkonsistent. Wenn wir nichts Konsistentes für 3.0 implementieren, würde ich vorschlagen, #5879 (das noch nicht in einer stabilen Version ausgeliefert wurde) zurückzusetzen, um die Einführung einer API zu vermeiden, die später ersetzt werden könnte.

Meine Implementierung ist zu 98 % fertig (sie funktioniert, aber es gibt einige Speicherlecks und zufällige Abstürze, für die ich keine Zeit zum Debuggen hatte), aber aufgrund von Zeitbeschränkungen im wirklichen Leben werde ich sie nicht fertigstellen können.

Ich bin mehr als bereit, mein WIP in einen Zweig zu stecken, damit jemand (mir helfen) es fertigstellen kann. Bei Fragen zur Umsetzung kann ich helfen. Es wäre eine Schande, wenn meine Mühe umsonst wäre (ich habe bisher wahrscheinlich etwa 40 Stunden damit verbracht)

Die Implementierung ist ziemlich vollständig (und ich bin eigentlich ziemlich stolz darauf, wie vollständig sie geworden ist), zum Beispiel funktioniert das Slicing wie in Python für die meisten Array-Typen, einschließlich der Zuweisung ( a[1:4] = [1,2,3] zum Beispiel funktioniert, tut es auch a[1:3] = b[10:13:2] und umgekehrt).

Es gibt jedoch ein paar Vorbehalte:

  • Die Implementierung ist ziemlich komplex, und Sie müssen etwas über Variant.cpp undvariant_op sowie den Bytecode-Interpreter wissen, um einen Sinn daraus zu machen.
  • Um bei Verstand zu bleiben und beim Debuggen zu helfen, musste ich einige der Makros invariant_op durch entsprechende Vorlagen ersetzen, meiner Meinung nach machen sie den Code besser lesbar (und mit aktivierten Optimierungen so schnell wie zuvor), aber da der Code auf 2.1 basiert, dort muss wahrscheinlich etwas umgestaltet werden, um mit 3.0 zu kompilieren; Da der Code WIP ist, hatte ich auch keine Zeit, ihn in separate Commits aufzuteilen, also wird manchmal ein Makro durch eine Vorlage ersetzt, während gleichzeitig auch die Variantenlogik hinzugefügt wird; es macht es etwas schwieriger (aber nicht zu schwierig), die beiden zu unterscheiden
  • Um zu vermeiden, dass der Bytecode-Interpreter mit alten Versionen inkompatibel wird, musste ich einen neuen Datentyp slice einführen, der im Editor verfügbar gemacht werden muss. Diese Arbeit ist erledigt, aber es gibt ein paar Ecken und Kanten.
  • Wie bereits gesagt, ist das "einzige" verbleibende Problem eine Speicherbeschädigung, die ich nicht herausfinden konnte; wer das debuggen will, sollte mit der Funktionsweise des Godot-Bytecode-Interpreters vertraut sein

Sag Bescheid, wenn ich den Code irgendwo einfügen soll. Ich denke, jemand, der mit den Interna des Godot-Skripts vertraut ist, wird die Knicke in 10 Stunden oder weniger ausbügeln.

@brakhane Da Sie bereits Arbeit geleistet haben, wäre es großartig, wenn Sie den Code in Ihren Fork einfügen und einen Pull-Request öffnen. Auf diese Weise können andere Personen Ihren Code überprüfen und kommentieren.

Wie geht's?
Ich freue mich darauf. :)

@bojidar-bg ist unser neuer gdscript-Entwickler, möchten Sie es ausprobieren? :P

Nun, werde auf 3.1 drängen

Ich wollte nur darauf hinweisen, dass die Subarray-Methode inklusive Bereiche verwendet, während dies (hoffentlich) Slicing-Bereiche im Python-Stil verwendet.

Ich sage hoffnungsvoll, weil die Subarray-Methode etwas schmerzhaft zu verwenden ist und Sie spezielle Groß- und Kleinschreibung schreiben müssen, um sicherzustellen, dass Sie niemals versuchen, ein Segment mit einer Breite von null zu erstellen (z. B. wenn Sie versuchen, einen Teil eines Puffers zu verbrauchen, indem Sie es zweimal schneiden, das 'verbleibende' Slice kann eine Länge von Null haben) und -1 zu allen Längen hinzuzufügen, wenn ein Slice angefordert wird.

Bearbeiten: Tatsächlich kann ich mir auf Anhieb keine Situation vorstellen, in der Sie dem End-Slice keine -1 hinzufügen müssten , es sei denn, Sie schneiden Bytes mit konstanter Anzahl und können so die -1 ausführen beim Schreiben.

Irgendwelche Fortschritte damit?
Ich habe gerade herausgefunden, dass ich diese Funktionalität in GDscript wirklich nutzen kann

Der Übergang zum nächsten Meilenstein, da 3.1 jetzt eingefroren ist (und für 3.2 verschiedene GDScript-Verbesserungen geplant sind).

Hallo, ich bin gerade auf diesen Artikel gestoßen und wollte meinen Senf dazu geben.

Wenn Smart Slicing in irgendeiner Weise die Leistung der Indizierung einzelner Arrays beeinträchtigt, sollten wir es wahrscheinlich vermeiden. Das Iterieren über Objekte in GDScript ist ein zu häufiger Anwendungsfall, um Leistungseinbußen für ein wenig syntaktischen Zucker zu erleiden.

Obwohl ich für syntaktischen Zucker bin, denke ich, dass der durchschnittliche Spieleentwickler vernünftige Erwartungen in Bezug auf Atomizität und Geschwindigkeit hat, wenn irgendetwas im Zusammenhang mit Klammern, geschweiften Klammern, Klammern usw. in GDScript implementiert wird. Wenn dieser Vertrag gebrochen wird, wird die Frage, wann ich etwas zu GDNative pushen sollte, viel verschwommener. Ich denke, eine gute "sub_array()"- oder "slice()"-Funktion wäre der beste Weg, denn dann (nehme ich an) könnten Sie den vorhandenen Array-Indizierungscode unverändert beibehalten.

Gibt es diesbezüglich Fortschritte? Ich könnte eine PR einreichen, die solche Methoden hinzufügt.

Wollen das trotzdem umgesetzt werden. Irgendwelche Neuigkeiten?

Dasselbe, ich möchte eine Teilmenge aus einem Array abrufen, und es scheint, als ob sowohl Listenverständnisse als auch eine Funktion zum Aufteilen eines generischen Arrays nicht existieren. Eines davon sollte wahrscheinlich hinzugefügt werden, da die Alternative etwas ausführlich ist.

@bojidar-bg

Beachten Sie, dass dies mit range und dem Verständnis aus #4716 einfach zu bewerkstelligen ist:

var result = array[from:to:step]
# Is the same as:
var result = (array[i] for i in range(from,to,step))

Das ist derzeit nicht korrekt, da die Verständnisse noch aufgenommen werden müssen. Die aktuelle Syntax lautet:

var result = []
for i in range(from, to, step):
    result.append(array[i])

Seltsamerweise lehnten die Entwickler eine PR für dieses Feature (#15222) aus Gründen der Lesbarkeit ab.

Wir haben dies im IRC mit vielen Core-Entwicklern diskutiert, und das allgemeine Gefühl ist, dass die Syntax von List Comprehensions den Code ziemlich schwer lesbar macht und gegen die Designprinzipien von GDScript verstößt, um eine geradlinige und leicht lesbare Syntax zu haben.

Ich persönlich finde die eine Zeile nicht schwerer zu lesen als die drei. Ist sonst noch jemand der Meinung, dass diese Unterhaltung wieder aufgenommen werden sollte?

@SnailBones Ich denke, eine eingebaute Array.slice() -Methode ist hier am sinnvollsten. Sprachen wie JavaScript haben eine ähnliche Funktion und scheinen dort gut zu funktionieren :slightly_smiling_face:

Ich denke, Listenverständnisse wären nett, aber ein separates Array.slice() zu haben, wäre trotzdem nützlich.

Ich arbeite gerade an einer Array.slice Methode

Wäre es besser, einen neuen Variant-Slice-Typ zu erstellen, wie es Python tut, wenn dieses Slice-Objekt als Operator in das Array eingegeben wird, oder dass der Aufruf der Slice-Funktion im Array im Compiler fest codiert ist? Ich habe die slice -Methode ausgeführt und möchte die start:end:delta -Syntax zur gdscript-Indizierung hinzufügen.

Das Slice-Objekt wäre eher "Pythonic" ;) aber die fest codierte Methode
wäre mit ziemlicher Sicherheit schneller. So oder so, mit der
Start:Ende :Delta-Syntax
wäre sehr hilfreich.

Am Samstag, 20. Juli 2019 um 18:05 Uhr Cameron Reikes [email protected]
schrieb:

Wäre es besser, einen neuen Variant-Slice-Typ wie how zu erstellen
Python macht es, wo dieses Slice-Objekt als ein in das Array eingespeist wird
Operator, oder für den Aufruf der Slice-Funktion im Array zu sein
im Parser fest codiert? Ich habe die Slice-Methode durchgeführt und ich suche
in das Hinzufügen der Start:Ende :Delta-Syntax zur gdscript-Indizierung.


Sie erhalten dies, weil Sie kommentiert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6P4A4CDQWUS4PSQQH3QAOK2JA5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2NXQ4Q#issuecomment-53905 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ACJUE6LOTSF243FOYXXR2SDQAOK2JANCNFSM4CEI4JPA
.

Ich denke nur daran, eine neue Slice-Variante zu verwenden, weil dann das Slicing ein Operator im Parser sein könnte und es besser funktionieren würde, aber ich bin nicht sehr erfahren auf diesem Gebiet, also wäre es großartig, eines der Gdscripts zu haben Entwickler stimmen ein.

Da haben Sie recht. Es wäre auch viel einfacher, die Syntax wiederzuverwenden
Struktur für andere Dinge später. Klingt für mich nach der besten Option.

Am Samstag, 20. Juli 2019 um 23:28 Uhr Cameron Reikes [email protected]
schrieb:

Ich denke nur an eine neue Slice-Art-Variante, weil dann das Slicing
könnte ein Operator im Parser sein und es würde besser funktionieren


Sie erhalten dies, weil Sie kommentiert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/godotengine/godot/issues/4715?email_source=notifications&email_token=ACJUE6IMHLNTYTVL7DITY2TQAPQX3A5CNFSM4CEI4JPKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2N3D4Q#issuecomment-51352 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ACJUE6P5Q55EXAWD6IB4ARDQAPQX3ANCNFSM4CEI4JPA
.

Ich werde mal sehen, ob ich meine alte Implementierung finde, die noch irgendwo rumliegt. Es war zu 90 % fertig und funktionierte ähnlich wie Python, da es ein Slice-Objekt gibt, das Sie verwenden können, um Arrays zu indizieren. Sie könnten sogar Sachen wie arr[2:4] = [1,2,3] machen.

Aus Zeitgründen habe ich die Arbeit daran abgebrochen

@brakhane Das wäre sehr hilfreich. Im Moment bin ich dabei, einen neuen Slice-Objektvariantentyp hinzuzufügen, damit das Slicen als Operation betrachtet werden kann, wodurch das Ändern des Parsers viel einfacher wird.

@creikey Das klingt meinem Ansatz ziemlich ähnlich. Ich habe mein Godot-GitHub-Repo gelöscht, aber möglicherweise liegt der Code noch woanders herum. Ich werde ein Update posten

@creikey Ich habe ein nicht ganz aktuelles WIP gefunden (möglicherweise fehlen in dieser Version einige Funktionen). Sie finden es hier: https://github.com/brakhane/godot/compare/4c4ab14..8a258c0

Es gibt noch einige Fehler, die mir zum Beispiel gerade hier aufgefallen sind https://github.com/brakhane/godot/compare/4c4ab14..8a258c0#diff -7d521a4f767fb1ae3c908a20616084a4R1446 es sollte ".end" statt ".start" heißen

Wenn Sie Fragen haben, beantworte ich diese gerne. Ich werde auch versuchen, eine neuere Version zu finden.

Ich bin jetzt der Meinung, dass das Hinzufügen von Pythonic Array Slicing und nicht nur einer Funktion mit einer inklusiven Obergrenze unnötige Komplexität hinzufügt, da dies die Erstellung einer neuen Variante bedeuten würde, mit wenig Nutzen im Vergleich zum einfachen Hinzufügen einer Methode.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen