Latex3: Lokale Variablen deklarieren

Erstellt am 18. Okt. 2017  ·  49Kommentare  ·  Quelle: latex3/latex3

Das Dokument Das expl3-Paket und die LaTeX3-Programmierung (v. 2017/09/18) gibt auf S. 7:

Die LaTeX3-Codierungskonvention besagt, dass alle Variablen vor der Verwendung deklariert werden müssen.

In ähnlicher Weise heißt es im Dokument The LaTeX3 Interfaces (v. 2017/09/18) auf S. 10:

... im Gegensatz zu Variablen, die immer deklariert werden müssen

expl3 bietet keine Möglichkeit, eine Variable lokal zu deklarieren; nur global. Es ist jedoch weiterhin möglich, eine lokale Variable mit den verschiedenen \..._set:N... Funktionen implizit zu erstellen.

Es ist ein Prinzip der strukturierten Programmierung, dass unnötiges Dumping von Variablen in den globalen Geltungsbereich vermieden werden sollte. Die TeX-Sprache bietet wie alle mir bekannten höheren Programmiersprachen (einschließlich C, C#, Fortran, Java, Lisp, Pascal und Python) ein Bereichskonstrukt zum Erstellen lokaler Variablen, nämlich Gruppen. Darüber hinaus unterstützt die Programmiersprache LaTeX3 selbst glücklicherweise die Erstellung lokaler Variablen, trotz der Vorschläge in den Handbüchern.

Meiner Meinung nach sollten die oben zitierten Ermahnungen aus den Handbüchern gestrichen und erklärt werden, dass Variablen nach Möglichkeit lokal angelegt werden können und sollen.

Darüber hinaus, wenn es tatsächlich gewünscht ist, einen Programmierstil zu fördern, bei dem alle Variablen deklariert werden, bevor sie verwendet werden (ich persönlich denke, dies ist eine Frage des Programmierstils, die dem individuellen Geschmack des Programmierers überlassen werden sollte), müssen Funktionen zum Deklarieren lokaler Variablen bereitgestellt werden, ebenso wie es Funktionen zum Deklarieren globaler Variablen gibt.

expl3 feature-request

Alle 49 Kommentare

Die aktuelle Position folgt einer Reihe von Experimenten des Teams, um ein Muster zu erstellen, das mit den TeX-Grundlagen funktioniert, die expl3 . Insbesondere ist es wichtig zu beachten, dass Variablen mit Hilfe von Makros oder mit Hilfe von Registern implementiert werden können, und bedenken Sie, wie TeX-Gruppierung funktioniert.

Bei der Verwendung von Registern (_z. B._ für den Typ int ) benötigen wir einen Allocator, um die Registernummer und die CS, die wir für den Zugriff verwenden, zu verknüpfen. Im Gegensatz dazu wird dies für makrobasierte Speicherung nicht benötigt. Während also \cs_set_eq:NN verwendet werden kann, um neue tl Namen zu generieren (zum Beispiel), wird es bei allem fehlschlagen, das Register verwendet:

\int_set_eq:NN \l_undeclared_int \l_tmpa_in

wird einen Fehler auslösen.

Es ist möglich, einen lokalen Registerzuordner zu erstellen, und das haben wir in der Vergangenheit für _zB_ \int_local_new:N ausprobiert. (Siehe das etex Paket für eine solche Implementierung oder schauen Sie sich die expl3 Historie an.) Das Team entschied sich schließlich dagegen, da es nicht gut zum TeX-Scoping zu passen schien. Der Schlüssel hierbei ist, dass die TeX-Gruppierung nicht auf Deklarationen, sondern auf expliziten Gruppen basiert und dass eine lokale Variable innerhalb aller verschachtelten Gruppen existiert:

\begingroup
  \def\foo{}
  \begingroup
  \show\foo

Als wir die lokale _Erzeugung_ von Variablen versuchten, schien die Gefahr zu bestehen, die Funktionsweise der TeX-Gruppierung zu verschleiern und Programmierer in die Irre zu führen.

Wir haben uns daher für eine 'all globale' _Deklaration_ von Variablen entschieden, aber sowohl für die lokale als auch für die globale _Einstellung_ solcher Variablen (die \l_... _versus \g_... Konvention). Damit wird das Wesentliche lokalisiert: der Wert. Wir empfehlen daher, dass sich alle Deklarationen auf der obersten Ebene befinden

\tl_new:N \l_my_tl
\int_new:N \l_my_int

...
\cs_new_protected:Npn \my_func:nn #1#2
  {
    \group_begin:
      \tl_set:Nx \l_my_tl { \tl_lower_case:n {#1} }

Bis heute scheint dieses Muster gut für die Aufgaben zu funktionieren, für die expl3 verwendet wurde.

In tex werden auch lokal definierte Variablen nach dem Ende der Gruppe nicht vollständig zerstört. Sie verwenden immer noch etwas String-Platz: https://tex.stackexchange.com/questions/316999/release-space-in-the-string-pool. Daher ist es imho besser, Variablen als globale Objekte zu betrachten.

@u-fischer Guter Punkt: Nicht einer, den wir damals tatsächlich in Betracht gezogen haben, aber es lohnt sich, daran zu denken.

Meiner Meinung nach ist dieser Ansatz falsch. Es verstößt gegen die Prinzipien der strukturierten Programmierung und gegen TeX, das die Erstellung lokaler Variablen ermöglicht. Es macht LaTeX3 auch inkonsistent, da einige Datentypen lokale Variablen aufnehmen und andere nicht.

Ich möchte Sie bitten, die lokale Erzeugung von Variablen aller Art wieder aufzunehmen. Dies gibt den Programmierern die Wahl: Wer es vorzieht, alle Variablen global zu definieren, kann dies tun, und diejenigen, die einige global und einige lokal definieren möchten, können dies auch tun.

Wenn es speicherbedingte oder andere Vorbehalte gibt, können diese in der Dokumentation erwähnt werden.

Am 18. Oktober 2017 um 21:17 Uhr schrieb EvanAad [email protected] :

Meiner Meinung nach ist dies ein falscher Ansatz, und ich möchte darum bitten
Sie stellen die lokale Erzeugung von Variablen wieder her. Dies gibt den Programmierern eine
Wahl: wer es vorzieht, alle Variablen global zu definieren, kann dies tun, und
wer einige global und andere lokal definieren möchte, kann dies auch tun.

für Variablen, die auf einem Registertyp basieren, weisen Sie Ressourcen von a . zu
fester globaler Pool, so dass die globale Zuweisung des Namens tatsächlich weitaus mehr ist
natürlich. Da wir von etex ausgehen, gibt es mehr als 256 Register von
bei jedem Typ kann das Zuordnungsverhalten vielleicht mehr versteckt werden
Könnte mit klassischem Tex, aber es ist immer noch ein grundlegendes Merkmal des
zugrunde liegendes TeX-System. expl3 kann nie eine ganz allgemeine Programmierung sein
Sprache: Es muss mit dem zugrunde liegenden TeX-System funktionieren. Du solltest nicht sein
Vergleich mit C#, aber mit anderen TeX-basierten Sprachen und insbesondere mit
\newcount und Freunde.

Es stimmt auch nicht wirklich zu sagen, dass alle anderen Sprachen Variablen zulassen
in lokalen Gültigkeitsbereichen deklariert, erlaubt Fortran zum Beispiel nur Variablen
am Anfang einer Funktion/Unterroutine deklariert.

Nichts davon bedeutet, dass wir definitiv keine lokale Deklaration hinzufügen würden
System, aber das Anziehen von Allzwecksprachen ist kein guter Anwendungsfall.
Es müsste vernünftige Anwendungsfälle innerhalb des Textsatzes geben, in denen
Die Verwendung eines globalen Deklarationssystems war ein Problem.

Die Tatsache, dass Fortran verlangt, dass Variablen zu Beginn einer Funktion/Unterroutine deklariert werden, bedeutet nicht, dass diese Variablen global sind. Wenn Sie darauf bestehen, einen Programmierstil zu fördern, bei dem alle Variablen deklariert werden müssen, sei es so, aber dann stellen Sie Funktionen zum Deklarieren lokaler Variablen bereit, die denen zum Deklarieren globaler Variablen entsprechen.

Die Begründung für den Umfang und die lokalen Variablen ist in erster Linie konzeptionell. Die Tatsache, dass die zugrunde liegende TeX-Engine einige der mit lokalen Variablen verbundenen Ressourcen nicht freigibt, ist nicht von der Hand zu weisen, aber meiner Meinung nach kann dies nicht der Grund sein, den Begriff des Bereichs und der lokalen Variablen auszulöschen. Mit Ausnahme von Power-Programmierern ist die zugrunde liegende Implementierung nicht von Belang; und für Power-Programmierer können Tipps und Vorbehalte in der Dokumentation angeboten werden.

Das Ansprechen von Allzwecksprachen ist kein guter Anwendungsfall.

Ich würde sagen, dass das Abweichen von den Prinzipien der strukturierten Programmierung, die in praktisch jeder Programmiersprache von den 1960er Jahren bis heute, einschließlich TeX, implementiert wurden, etwas sein sollte, für das das LaTeX3-Team sehr zwingende Gründe haben sollte. Die Beweislast sollte bei denen liegen, die das, was allgegenwärtig als gute Programmierpraxis angesehen wird und bereits in TeX existiert, abschaffen wollen; nicht auf diejenigen, die es bewahren wollen.

@EvanAad Token-Liste, global darum zu kümmern, damit die Zuweisung kein bereits zugewiesenes Register berührt.

Angenommen, Ihrer lokalen Integer-Variablen \x wird das Register 100 zugewiesen, das bereits von der Variablen \y auf einer höheren Ebene belegt ist; Die Verwendung von \y auf derselben Ebene, auf der \x lokal definiert ist, wäre einfach katastrophal. Somit ist eine globale Buchführung von zugewiesenen Registern erforderlich, was es sehr schwierig macht, lokal zugewiesene Register freizugeben. Das Reservieren eines Registerblocks für lokale Zuweisungen ist keine Lösung.

Ich sage nicht, dass es nicht möglich ist, aber ich denke nicht, dass es den Schmerz wert ist.

Sie übersehen die Tatsache, dass \newcount nicht einfach lokal (oder global) ist
einen Namen deklarieren, assoziieren Sie einen Namen mit einem extern definierten Fix
Ressource. es gibt nur ein Zählregister 42 und alle Namen, die
als count42 deklariert sind beziehen sich auf das gleiche Register, ob
die Namensvergabe ist lokal oder global. Wie gesagt Vergleiche mit anderen
Sprachen sind nicht so nützlich, aber wenn Sie einen Vergleich wünschen, sollten Sie
Vergleichen Sie die Zuordnung von Dateiströmen oder ähnlichem: Sie können nicht immer isolieren
lokale Deklarationen, wenn sie eine Schnittstelle zu einem extern definierten
Ressource.

Am 18. Oktober 2017 um 21:43 Uhr schrieb EvanAad [email protected] :

Die Tatsache, dass Fortran erfordert, dass Variablen am Anfang von a . deklariert werden
Funktion/Unterprogramm bedeutet nicht, dass diese Variablen global sind. Da ich
schrieb, wenn Sie darauf bestehen, einen Programmierstil zu fördern, bei dem alle Variablen
muss deklariert werden, sei es so, aber dann Funktionen zum Deklarieren von local bereitstellen
Variablen, die denen für die Deklaration globaler Variablen entsprechen.

Die Begründung für das Scoping und lokale Variablen steht im Vordergrund
konzeptionell. Die Tatsache, dass die zugrunde liegende TeX-Engine einige nicht freigibt
der Ressourcen, die lokalen Variablen zugeordnet sind, ist nicht zu verwerfen,
aber meiner Meinung nach kann dies nicht der Grund sein, den Begriff auszulöschen
des Bereichs und der lokalen Variablen. Mit Ausnahme von Leistungsprogrammierern, die
die zugrunde liegende Umsetzung spielt keine Rolle; und für Power-Programmierer, Tipps
und Vorbehalte können in der Dokumentation angeboten werden.


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/latex3/latex3/issues/410#issuecomment-337721923 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/ABNcAimMfBDqA-e96Q7tkS-ERr5fv_2Mks5stmLqgaJpZM4P-Mpq
.

Der entscheidende Punkt ist, dass, wie Joseph und David erwähnt haben, die lokale Definition von int s möglich ist (und wurde ). Ich denke , es ist der Schmerz , um lohnt sich eine Sprache , die präsentiert eine einheitliche Abstraktionsschicht , die in Übereinstimmung mit den Prinzipien der strukturierten Programmierung zu erstellen.

Es fällt mir jedoch leicht zu sagen, dass es den Schmerz wert ist, da ich nicht derjenige bin, der den Schwierigkeiten bei der Implementierung der LaTeX3-Sprache ausgesetzt ist. Lassen Sie uns also gnädig vorgehen und sagen, dass es den Schmerz in der Tat nicht wert ist. Bußgeld. Teilen Sie die Datentypen in diesem Fall in zwei Kategorien ein: solche, die die Erstellung lokaler Variablen ermöglichen, und solche, die dies nicht tun. Und beschreiben Sie diese Kategorien in den Handbüchern. Sagen Sie nicht: Alle Variablen müssen vor der Verwendung deklariert werden. Sagen Sie: "Es gibt zwei Kategorien von Datentypen. Die erste, bestehend aus cs , tl , clist , ... beherbergt lokale Variablen und die zweite, bestehend aus int , ... nicht." Und erklären Sie, warum die zweite Kategorie existiert. Auf diese Weise ist die Dokumentation den Tatsachen getreu und die Programmierer sind gut informiert und haben die Wahl. Manche Programme brauchen überhaupt keine Datentypen der zweiten Kategorie zu verwenden, und warum sollte der Programmierer in diesen Fällen globale Variablen deklarieren?

@EvanAad Ich vermute, dass dies daran liegt, dass ich an die TeX-Programmierung \l_... / \g_... ). Die Tatsache, dass sie global zugewiesen/'reserviert' sind, stört das nicht.

Übrigens, wir möchten Schnittstellen nicht an die Implementierung binden: Zum Beispiel hat der Datentyp prop mindestens ein paar verschiedene Implementierungen, die mir bekannt sind, von denen eine Register verwendet und die aktuelle Makros verwendet.

Um dem noch eine Anmerkung hinzuzufügen, der Strohhalm, der dem Kamel (in meiner Erinnerung) den Rücken brach, dass das lokale Register-/Variablenzuweisungssystem zusammenbrach, lag an Inkonsistenz . Da sich Makros und Register unterschiedlich verhalten haben, kam es beim Schreiben zu einem anderen Verhalten

\group_begin:
  \int_new_local:N \l_tmpa_int
  \int_gset:Nn \l_tmpa_int {7}
\group_end:
% `\l_tmpa_int` undefined

vs

\group_begin:
  \tl_new_local:N \l_tmpa_tl
  \tl_gset:Nn \l_tmpa_tl {7}
\group_end:
% `\l_tmpa_tl` defined as `7`

Und die einzige Möglichkeit, dieses Problem zu lösen, wäre, ein Zuordnungssystem für Makros zu schreiben, das aufgrund des Overheads nie ernsthaft in Betracht gezogen wurde. (TeX verlangsamt sich, je mehr Variablen definiert werden, und so könnte eine Verdoppelung der Anzahl der Token-Listen die Leistung merklich beeinträchtigt haben.)

Ich denke immer noch, dass expl3 das Richtige getan hat, indem es Makros und Register in Funktionen abstrahiert hat, die gleich aussehen und sich gleich anfühlen – und wenn der Nachteil ist, dass die Syntax natürlich keine wirklich lokalen Variablen und Register unterstützt, die gesehen haben aus den oben genannten Gründen extrem eingeschränkte Verwendung in TeX, dann ist das aus meiner Sicht ein akzeptabler Kompromiss.

@wspr Aber die Beispiele, die Sie als diejenigen zitiert haben, die dem Kamel den Rücken gebrochen haben, sind Beispiele, in denen der Programmierer die Sprache missbraucht hat, indem er global einer lokalen Variablen \l_... kann, als ob sie global wäre.

... das entspricht den Prinzipien der strukturierten Programmierung.

das ist eine ziemlich kühne Aussage, da es mehr als einen Satz von gibt
Prinzipien und da versucht wird, verschiedene Prinzipien in
Supersets haben in der Vergangenheit normalerweise große, aber nutzlose Sprachen geschaffen.

Der entscheidende Punkt ist nicht unbedingt, dass etwas getan werden kann (wie
innerhalb von Turing-Komplettbasen sind auf dieser Ebene alle Dinge gleich) aber
ob etwas effizient und konsequent erledigt werden kann usw.

@wspr : Warum hast du dieses Problem wie ein Tyrann geschlossen? Es ist alles andere als geregelt.

@EvanAad – versuche nur,

Ich schließe diese Probleme vorübergehend aufgrund einiger hitziger Kommentare.

Ich denke, das ist eine relevante Frage. Ein Ergebnis dieser Diskussion sollte zumindest sein, dass wir im Dokument genauer beschreiben, warum wir nur globale Deklarationen gewählt haben. @EvanAad Ich glaube, Sie wissen die Einschränkungen des TeX-Systems nicht ganz zu schätzen, aber lassen Sie uns einen Schritt zurücktreten und dieses Problem für einen Moment ignorieren. Könnten Sie ein Beispiel (von sagen wir 10-20 Zeilen) geben, das ein hypothetisches \int_local_new:N oder ein anderes System Ihrer Wahl mit der Semantik Ihrer Wahl verwendet? Es würde helfen, die Diskussion in einen konkreteren Rahmen zu bringen, und wir können Vor- und Nachteile herausrechnen.

Vermutlich müssen wir warten, bis die Sperre aufgehoben wird, ich weiß nicht, wie das geht. Auf jeden Fall werden die meisten Leute in diesem Gespräch ein paar Stunden schlafen. (Übrigens, ich denke nicht, dass es sehr vernünftig war, #410 in #411 als eine durcheinandergebrachte Diskussion zu kopieren.)

Angesichts der Tatsache, dass dies eine ziemlich detaillierte Diskussion ist, lohnt es sich meiner Meinung nach, die technische und soziale Geschichte zusammenzufassen, die uns dahin gebracht hat, wo wir sind.

Auf technischer Ebene stellt TeX Register und Makros zur Speicherung bereit. Makros können einfach mit \def 'erstellt' werden, aber um Register nach Namen zu verwenden, benötigen wir einen Allocator, um die globale Registernummer, _zB_ \count40 , mit einem Namen zu verknüpfen, zB \mycount . Das wurde vom ersten Tag an bereitgestellt, wobei der einfache TeX \newcount _etc._ das Modell liefert. Im Klartext, \newcount allokiert global und führt trotz des Namens keine Überprüfung durch. Andere Formate, insbesondere LaTeX2e und ConTeXt, haben diesen Ansatz im Allgemeinen übernommen. Sie haben auch allgemein die Idee übernommen, dass einzelne Register dann entweder lokal oder global _zugewiesen_ werden, da dies den Aufbau von Sicherungsstapeln verhindert.

TeX90 stellte nur 256 Register der üblichen Typen zur Verfügung, daher war die Wiederverwendung von Registern in lokalen Kontexten von entscheidender Bedeutung. Man sieht, dass in _z. B._ graphics wo der Code „gesund“ gehalten werden soll, eine große Anzahl von Registern innerhalb einer Gruppe neue Namen erhalten und rein lokal verwendet werden. Mit e-TeX haben wir _viel_ mehr Register, daher ist dieser Ansatz weniger notwendig: Wir können mehr Register (und Makros) für dedizierte Zwecke frei zuweisen. Insbesondere bedeutet dies, dass wir nicht so unter Druck stehen, Register unter mehreren Namen zu „recyceln“.

Die Codebasis von expl3 ist seit _langer_ Zeit in Entwicklung und benötigte ursprünglich kein e-TeX. Die Entwicklung von expl3 erfolgt ebenfalls in erster Linie 'auf' LaTeX2e, mit dem allgemeinen Prinzip, dass expl3 weder den Dokumentennamensraum verschmutzt noch das Kernverhalten von LaTeX2e verändert.

Insbesondere müssen wir bedenken, dass \newcount LaTeX2e dem

\def\foo{%
  \begingroup
    \newcount\localfoocnt

'schlechter Stil' ist, als ob \foo mehrmals aufgerufen wird, dann verbrauchen wir Register, die nie freigegeben werden.

Für expl3 hat das Team versucht, das dokumentierte Verhalten von Variablen nicht an die Implementierung von Makros oder Registern zu binden. (Ich stelle fest, dass wir die Verwendung von tl ohne Accessor zulassen, was letztendlich darauf beruht, dass es sich um Makros handelt.) Wir verwenden auch weiterhin Register für Ganzzahlen, Dimensionen usw., wie sie verfügbar sind und anbieten bessere Leistung und 'Selbstbeendigung' als alles in Makros zu tun. (Das wäre mit e-TeX und den verschiedenen \<thing>expr Primitiven machbar.) Daher benötigen wir ein Zuweisungssystem, und um konsistent zu sein, weisen wir alle Variablentypen zu, nicht nur diejenigen, die auf Registern basieren . Wie @EvanAad beobachtet hat, kann man, wenn die Überprüfung nicht aktiv ist, _z. B._ \tl_set_eq:NN \l_new_tl \l_existing_tl ohne Fehler ausführen, aber dies ist nicht das unterstützte Verhalten (durch Überprüfung wird es zum Beispiel angezeigt).

Als Teil des expl3 Allocators wurde die Entscheidung getroffen, dass new _würde_ auf Existenz prüfen würde, im Gegensatz zu \newcount , also

\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_new:N \l_my_tl

wird einen _error_ auslösen, wenn \my_foo: wiederholt verwendet wird. Dies treibt einen in die Richtung, die seit den ersten Tagen des Klartextes gängige TeX-Praxis ist: Allokationen gehen außerhalb des Makros. (Beachten Sie, dass \newcount einfach \outer ist und daher in Makros "verboten" ist.)

\tl_new:N \l_my_tl
\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_clear:N \l_my_tl

Das Paket etex führte vor vielen Jahren einen Registerzuordner ein, der sowohl lokale als auch globale Registerzuweisungen durchführen kann, \loccount _versus_ \globcount , _etc. Für einige Zeit wurde expl3 etex expl3 geladen und es wurde verwendet, um Funktionen für \int_local_new:N und ähnliches bereitzustellen. Angesichts der Tatsache, dass die meisten TeX-Programmierer es gewohnt sind, globale Allokation durchzuführen, ist es vielleicht nicht überraschend, dass dies nicht so weit verbreitet ist. Allerdings machte sich das Team auch Sorgen über mögliche Missverständnisse. Mit sowas wie

\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_local_new:N \l_my_tl

Wir haben die Frage, was bei verschachtelten Aufrufen von \my_foo: passiert, oder wahrscheinlicher an Orten, an denen ein 'einfacher' Name wie \l_my_tmp_tl verwendet werden soll. Basierend auf der allgemeinen Idee, dass new Prüfungen durchführen soll, sollte dies ein Fehler sein. Programmierer, die aus vielen anderen Sprachen kommen, finden das vielleicht etwas seltsam. Natürlich passt es zu den Scoping-Regeln von TeX.

Bemerkenswerterweise bedeuteten Änderungen am LaTe2e-Kernel in den letzten Jahren, dass wir etex nicht mehr laden wollten (tatsächlich haben wir hart daran gearbeitet, expl3 'eigenständig' zu machen). Jeder neue lokale Allocator müsste also geschrieben werden, um mit LaTeX2e zu arbeiten, ohne das Verhalten für diejenigen zu "stören", die expl3 : machbar, aber nicht ganz trivial.

Für so etwas wie \l_my_tmp_tl könnte man natürlich noch eine globale Allokation machen, aber dann muss man wissen, welche \l_... Variablen in der aktuellen Gruppe lokal allokiert sind und welche global allokiert aber lokal zugewiesen sind.

Ich habe keine Testdaten zur Hand, aber es ist wahrscheinlich erwähnenswert, dass das Zuordnen einer Variablen mehr Arbeit ist als das einfache Setzen (sicherlich, wenn die Überprüfung nicht aktiv ist), daher wäre die Verwendung eines lokalen Allocators etwas langsamer als ein globaler Allocator plus lokale Aufgaben.

Aus einer Mischung aus technischen Gründen und „passend zur Geschichte“ haben wir uns daher entschieden, bei der strikt globalen _Zuordnung_ zu bleiben. Dies verhindert in keiner Weise die lokale _Zuweisung von Variablen, die ermutigt und sehr häufig verwendet wird.

Das bringt uns zum „sozialen“ Element. Die Inanspruchnahme von expl3 in den letzten Jahren wurde stark unterstützt, indem die Teile „weitgehend“ stabil gemacht wurden. Irgendwann muss das Team Entscheidungen treffen, teils, damit die Leute es nutzen können, und teils, damit wir uns anderen Aufgaben zuwenden. Das hindert uns nicht daran, Dinge noch einmal zu überdenken, aber etabliertere Konventionen brauchen einen guten Grund, um geändert zu werden.

Hier sehe ich derzeit wohl nicht, was an der 'üblichen' Herangehensweise falsch ist

\tl_new:N \l_my_tl
\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_clear:N \l_my_tl

Zumindest bis zu dem Punkt, an dem es erforderlich ist, dass wir zurückgehen und das aktuelle Setup ändern.

@blefloch Ja, ich stimme zu, dass meine Reaktion auf das Schließen des Threads durch @wspr unvernünftig war und ich entschuldige mich bei ihm und dem Rest von Ihnen. Ich fühlte mich entlassen und zum Schweigen gebracht und reagierte mit einem Wutanfall. Das ist inakzeptabel. Das tut mir leid.

@josephwright danke für die ausführliche Antwort. Nach einigem Nachdenken habe ich festgestellt, dass, wenn ich nur \<module>_clear_new:N , sich alle meine Variablen so verhalten, als wären sie lokal für die umgebende Gruppe, solange ich mit \<module>_set... zuweisen \<module>_gset... . Darüber hinaus denke ich, dass diese Vorgehensweise mit der LaTeX3-Konvention übereinstimmt, eine Variable vor der Verwendung zu deklarieren, sodass ich nicht markiert werde, wenn die Prüfungen aktiviert sind.

Nach dieser Praxis würde ich @josephwright letztes Beispiel so umschreiben:

\cs_new_protected:Npn \my_foo:
{
    \group_begin:
        \tl_clear_new:N \l_my_tl

Der einzige Datentyp, der nicht in dieses Schema passt, ist cs , aber soweit ich weiß, ist es legal, Variablen dieses Typs mit \cs_set:Npn et al. ohne sie vorher zu deklarieren, denn LaTeX3 behandelt cs nicht wirklich als normalen Datentyp auf Augenhöhe mit den anderen (was ein separates Thema ist, das ich gerne mit euch ansprechen würde, aber ich werde gehen es in einen anderen Thread). Mit diesem Ansatz können auch cs Variablen lokal erstellt werden. Wenn ich die Syntax konsistent halten möchte, kann ich jederzeit meinen eigenen \cs_clear_new:N Wrapper schreiben.

Soweit es mich betrifft, können Sie dieses Problem jetzt schließen, wenn Sie möchten, @wspr .

@EvanAad Beachten Sie bei \<thing>_clear_new:N , dass die Deklaration _global ist, wenn die Variable noch nicht existiert. So

\cs_new_protected:Npn \my_foo:
{
    \group_begin:
        \tl_clear_new:N \l_my_tl
    \group_end:
}
\my_foo:
\tl_show:N \l_my_tl

zeigt, dass \l_my_tl definiert und leer ist, vorausgesetzt, Sie haben es vorher nicht auf etwas anderes gesetzt.

Ich würde mich @blefloch gerne anschließen

  1. Wird das Verhalten der Sprache undefiniert sein?
  2. Wird die Nichteinhaltung derzeit unterstützt, wird dies jedoch in zukünftigen Versionen möglicherweise nicht mehr sein?
  3. Meldet der Motor einen Fehler?
  4. Wird der Motor einen Fehler melden, aber nur, wenn die Überprüfungen eingeschaltet sind?
  5. Wird es zu kleineren Unannehmlichkeiten kommen?
  6. Wird das LaTeX3-Team unzufrieden murren, aber es kommt zu keinem Fehler oder Verlust der Funktionalität?

Nehmen Sie als Beispiel für 5 die Konvention, Argumentspezifikationen an das Ende eines Funktionsnamens anzuhängen. Soweit ich das beurteilen kann, ist die einzige Funktion, die nicht richtig funktioniert, wenn diese Konvention nicht eingehalten wird, \cs_new:Nn , aber der Rest, einschließlich `cs_new :Npn ', funktioniert einwandfrei.

Nehmen Sie als Beispiel für 6 die Konvention, lokale und globale Variablen mit \g_... und \l_... markieren. Soweit ich weiß, wird die Nichtbefolgung dieser Konvention absolut keine Auswirkungen haben. Alles wird richtig funktionieren.

@EvanAad – Entschuldigung angenommen, und es tut mir meinerseits leid, dass ich das Problem geschlossen habe, bevor die Diskussion abgeschlossen war.

@josephwright – als ein winzig kleiner Vorteil der Vorteile für die lokale Zuteilung, wenn ich schreibe

\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_new_local:N \l_my_tl
      ...

dann weiß ich, dass \l_my_tl nicht nur frei von Störungen von außen ist, sondern im Gegensatz zu einer _clear Funktion weiß ich, dass alle Spuren der Variablen außerhalb der Verwendung der Funktion verloren gehen. Mit anderen Worten, wenn ich mir \tl_if_exist_p:N .)

(Muss ausgeführt werden, kann aber später fortgesetzt werden, wenn es einen Sinn gibt, weiter zu diskutieren.)

@wspr Ja, aber das ist zurück mit der Tatsache, dass es auf dem TeX-Gruppenbereich basiert. Es kann also 'semi-global' in einem Konstrukt der Form . verwendet werden

\cs_new_protected:Npn \my_foo:
  {
    \group_begin:
      \tl_new_local:N \l_my_tl
      \tl_set:Nn \l_my_tl { foo }
      \__my_foo:
     ..
  }
\cs_new_protected:Npn \__my_foo:
  {
    \group_begin:
        \tl_use:N \l_my_foo % Definition from \my_foo: => "foo"
...
  }

was zumindest ein Teil unseres Denkens war.

Ich denke, bevor wir dies verlassen, möchte ich betonen, dass es auf technischer Ebene eine Reihe von Möglichkeiten gibt, einen lokalen Registerzuordner einzurichten.

@josephwright – Ich habe das jedoch noch nie als verwirrendes Beispiel gesehen; in Matlab zum Beispiel unterscheiden sie zwischen Unterfunktionen, die keinen gemeinsamen Gültigkeitsbereich haben, und verschachtelten Unterfunktionen, die dies tun. Meines Erachtens war das immer: Warum sollte \__my_foo: den Geltungsbereich der „äußeren“ Funktion erben? Es stimmt perfekt mit dem Gruppierungsverhalten von TeX überein.

(Entschuldigung, dass ich die Diskussion weiterführen muss. Es war ein langer Tag. Ist jemand daran interessiert, tatsächlich fortzufahren?)

Am 19.10.2017 um 09:23 schrieb Joseph Wright:

Ich denke, bevor wir dies verlassen, möchte ich das bei a . betonen
Auf technischer Ebene gibt es verschiedene Möglichkeiten, ein lokales Register einzurichten
Zuweiser.

ja, aber ziemlich nahe am Turing-Argument, dh einer solchen Implementierung
wird zur Laufzeit sehr ineffizient sein, da die zugrunde liegende Engine
verwaltet den Registerspeicher global. Und expl3 (auf dieser Ebene)
soll "angemessen effizient" bleiben.

das ist wie beispielsweise globale und lokale Variablen und ihr Mutator. Eher
als in jeder Funktion zu testen, wenn sie eine globale Operation auf a ausführt
lokale Variable, das Konzept ist standardmäßig nur in den Namen vorhanden,
zB \l_... soll eine lokale Variable sein und sollte nicht verwendet werden
mit einer globalen Funktion wie ..._ gset:Nn aber das testen wir nicht bei
Laufzeit

Wir bieten jedoch ein Check-Modul an (welches wie oft langsamer läuft)
Das stellt sicher, dass all diese Konventionen tatsächlich eingehalten werden.

Um auf globale/lokale Variablen zurückzukommen

das Standardkonzept von expl3 ist

  • deklarieren Sie den Namen einer Variablen einmal (global) -- viele, weil at
    zumindest einige der Typen haben nur Globallagerplätze

  • Verwenden Sie die Namenskonvention \l_ \g_, um lokale und globale Variablen zu bezeichnen

das gibt Ihnen sowohl Globals als auch Locals, hat aber die Einschränkungen, die

  • Sie deklarieren eine lokale Variable nicht am Anfang ihres Gültigkeitsbereichs,
    stattdessen verwenden Sie an dieser Stelle entweder _set oder _clear_new und letzteres
    kann bedeuten, dass der Name der Variablen an dieser Stelle global vorkommen kann
    in Existenz

  • außerhalb des Gültigkeitsbereichs existiert die Variable immer noch mit der Vorgabe
    Wert des Typs (zB _int ist 0 usw.), damit Sie keinen Compiler erhalten
    Fehler, wenn Sie "aus Versehen" auf eine solche Variable verweisen, die nicht beabsichtigt ist
    Umfang

Das einzige, was Sie also nicht bekommen, ist im Grunde die Möglichkeit, a zu deklarieren
lokale Variable, sodass ihr Name außerhalb des Gültigkeitsbereichs verschwindet (und erzeugt
ein undefinierter Fehler irgendeiner Art zur Laufzeit, wenn außerhalb des
deklarierter Geltungsbereich).

Um das zu tun (was ja möglich ist), müsste expl3 seine eigenen pflegen
Ressourcenpool weit über eine einfache Assoziation zwischen einem Namen und einem globalen hinaus
Pool, der von der Engine angeboten wird, und das würde bedeuten, dass alle Zugriffe
sehr deutlich verlangsamt erledigt - was gegen die Designkriterien von expl3 verstößt.

@FrankMittelbach — jetzt hast du mich neugierig gemacht; Ist der etex.sty-Ansatz für Register wirklich so ineffizient? Oder vielleicht meinst du für tl-Variablen, in diesem Fall stimme ich zu!

@FrankMittelbach Meiner Meinung nach ist es wichtig zu unterscheiden und in der Dokumentation deutlich zu machen, was laut dem LaTeX3-Team eine Best Practice ist und was eine formale Anforderung, entweder grammatikalisch oder semantisch, der Regeln der LaTeX3-Sprache ist.

Die beiden von Ihnen zitierten Regeln, nämlich:

  • den Namen einer Variablen einmal (global) deklarieren
  • Verwenden Sie die Namenskonvention \l_ \g_ um lokale und globale Variablen zu bezeichnen

fallen unter diese Rubrik von Kodierungskonventionen, die das LaTeX3-Team für ratsam hält, aber keine von ihnen ist durch die grammatikalischen Regeln der Sprache vorgeschrieben, und die Nichteinhaltung dieser Konventionen verursacht keine Fehler oder Funktionsverluste.

Mit anderen Worten, die Einhaltung dieser Regeln ist eine Frage des persönlichen Geschmacks und des Programmierstils, und dies sollte meiner Meinung nach in der Dokumentation klargestellt werden.

das ist ein bisschen so, als würde man sagen, dass das Zeichen 50mh keine Regel ist, sondern ein Fahren
Konvention und es ist Geschmackssache, ob sich ein Fahrer daran hält (nur
weil es meistens nicht sofort geprüft wird)

Wenn Sie eine \l_-Variable mit _gset verwenden, programmieren Sie immer noch in TeX, aber
Sie haben aufgehört, den grammatikalischen Regeln des expl3 zu gehorchen
Sprache. Wird Ihr Code sofort gebrochen? wahrscheinlich nicht, aber du
Savestack-Aufbau generieren (siehe TeXbook-Index)

Sagen Sie, es ist nur eine grammatikalische Regel, wenn wir es überprüfen?
Laufzeit, sagen wir, jeden Dienstag?

@FrankMittelbach Sicher, wenn Sie definieren diesen Teil der Regeln der Sprache zu sein , als es so per Definition ist, aber mein Punkt ist , dass dies nicht im Rahmen der Regeln der Sprache definiert werden soll, weil es nie geprüft wird, und denn die Nichtbeachtung dieser Konvention führt an sich noch nicht zu einem Fehler oder Funktionsverlust.

Es ist der Unterschied zu sagen: "Wenn Sie Englisch schreiben, halten Sie den Stift am besten in der rechten Hand, da dies ein Verschmieren der Tinte verhindert." und ein Gesetz zu verabschieden, das besagt, dass Englisch mit dem Stift in der rechten Hand geschrieben werden muss. Sicher, Sie können ein solches Gesetz erlassen, und es gibt gute Gründe, es zu rechtfertigen, aber letztendlich sollte die Wahl, in welcher Hand er den Stift hält, dem einzelnen Autor überlassen bleiben. Und es wird Leute geben, die sich nicht an diese Regel halten und trotzdem genauso ordentlich schreiben wie diejenigen, die sich daran halten.

Ich denke, @FrankMittelbach übertreibt den Overhead lokaler Deklarationen ( \loccount verwaltet Zählungen lokal, nichts, was es tut, ist global, so dass der Overhead in Ordnung bleibt).

Ich sehe kein größeres Problem darin, ein \int_local:N und \tl_local:N (= \tl_set_eq:NN #1 \c_empty_tl ) usw. bereitzustellen, die sehr analog zu \int_zero_new:N und \tl_clear_new:N wären würde aber nur "neu" lokal machen. Dies erfordert ein wenig Arbeit für Register, aber nicht übermäßig.

@EvanAad Sie sollten wissen, dass das

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\tl_put_left:cn { l_my_tl } { foobar \par }
\l_my_tl
\end{document}

@blefloch Was ich sage ist, es ist völlig in Ordnung, eine Variable innerhalb eines Makros zu deklarieren (mit \<module>_clear_new ), und Sie müssen sie nicht \l_amount_paid_int , Sie können einfach anrufen it \amount_paid oder \amountPaid , wie Sie es in jeder anderen Programmiersprache tun würden. Das \l_..._int ist eine nette Mnemonik, um Sie daran zu erinnern, dass es ganzzahlig ist und lokal verwendet werden soll, aber Sie sollten nicht gezwungen werden, diese oder eine andere Mnemonik zu verwenden.

weil es nie überprüft wird und weil diese Konvention nicht eingehalten wird
verursacht an sich keinen Fehler oder Funktionsverlust.

aber das ist der Punkt

a) es verursacht je nach Umständen Schaden – nämlich wenn man mischt
globale und lokale Zuweisungen an dieselbe Variable

b) Wir überprüfen auf Anfrage (und im Moment ist dieser Code möglicherweise nicht vorhanden)
funktionsfähig, aber es war und wird wahrscheinlich irgendwann wieder sein wegen a))

ps ja, ich verstehe deinen Standpunkt zum Stifthalten (Linkshänder zu sein) und ja, ich
Ich habe die Geschwindigkeitsbegrenzung überschritten (auf meinem Fahrrad), aber ich betrachte dies immer noch als
Verkehrsregeln sind keine Verkehrsregeln und ja, das kann man missachten
ohne Schaden, aber man kann auch daran sterben oder zumindest mit einer Geldstrafe enden

(Was mein vorheriges Codebeispiel gezeigt hat, ist, dass es selbst für tl wichtig ist, sie vor der Verwendung zu deklarieren. Es gibt eine Prüfoption, die Deklarationen testet, aber im normalen Gebrauch wollen wir solche Overheads nicht.)

Ich stimme @EvanAad zu, dass Namen nur eine Konvention sind. Wir können auch ohne die l_/g_-Namenskonvention überprüfen, dass lokale und globale Zuweisungen nicht vermischt werden: Da der Prüfcode etwas langsam sein darf, ist es durchaus sinnvoll, die Information darüber zu speichern, ob eine gegebene Variable in einem lokalen/globalen verwendet wurde Abtretung. Bei der Überprüfung von Typen ist die Situation ähnlich, mit Ausnahme von zwei Paaren von Typen, die nicht unterschieden werden können (ich werde nicht sagen, welche, um die Konversation nicht zu entgleisen).

Auf 'conventions' ist \amountPaid ein Dokumentbefehl, während \l_amount_paid_int es nicht ist, und letzteres ist Teil des amount Namensraums (per Konvention, aber ein ziemlich wichtiger in TeX ). Das gilt nicht für \l_ / \g_ , obwohl ich denke, dass viele Sprachen eine starke "Steuerung" bei der Benennung haben, ohne dass dies auf technischer Ebene durchgesetzt wird.

Am 19. Oktober 2017 um 16:58 Uhr schrieb Joseph Wright [email protected] :

Auf 'Konventionen' ist BetragPaid ein Dokumentbefehl, während \l_amount_paid_int nicht ist, und letzteres ist Teil des Betrags-Namensraums (nach Konvention, aber ein ziemlich wichtiger in TeX). Das gilt nicht für \l_/\g_, obwohl ich denke, dass viele Sprachen eine starke "Steuerung" bei der Benennung haben, ohne dass dies auf technischer Ebene durchgesetzt wird.

Der schlimmste Albtraum in der LaTeX2e-Programmierung ist die Definition eines Befehls
im „Raum auf Benutzerebene“, sagen Sie \foo, um zu entdecken, dass es kollidiert
mit einem Befehl ein anderes Paket definiert für _intern_ verwenden (so
nicht im Handbuch dokumentiert).

Ist es wirklich passiert? Ja, und nicht nur einmal. Festhalten an der
\@commandname- Konvention hat sehr geholfen, dies zu vermeiden
solche Probleme.

Natürlich kann es auch auf der „Benutzerebene“ zu Konflikten kommen,
aber sie sind viel einfacher zu erkennen und zu lösen. Wenn es um die . geht
Interna ist es oft notwendig, Erweiterungen sehr schnell hinterher zu jagen
tiefe Ebene.

Anders als der Gesetzgeber können wir keine Geldstrafen oder Gefängnisstrafen verhängen
die sich nicht an die Gesetze der LaTeX3-Programmierung halten. Aber waren
eine Gemeinschaft und jeder sollte.

Unsere Richtlinien zu Namenskonventionen sollen dabei helfen, nie zu finden
die internen Befehle eines Pakets, um mit anderen zu kollidieren.

Beim persönlichen Code darf man machen was man will: es gibt
kein Gesetz, das es einem verbietet, in seinem Privateigentum zu rasen, aber
Es gibt eine davon, dies auf einer öffentlichen Straße zu tun.

Wenn Sie die Variable \f eines beliebigen Typs lokal definieren möchten,
Sie sollten sich Sorgen machen, dass der Befehl von einigen definiert wird
Paket und endet nach Murphys Gesetz genau im Argument
zu einer Funktion mit der Variablen \f. Kannst du dir was schlimmeres vorstellen
Szenario?

Ciao
Enrico

und Sie müssen es nicht \l_amount_paid_int nennen, Sie können es einfach wie in jeder anderen Programmiersprache wie folgt benennen. \l_... ist eine nette Mnemonik, um Sie daran zu erinnern, dass sie lokal verwendet werden soll, aber Sie müssen weder diese noch eine andere Mnemonik verwenden.

Sicher. Sie könnten auch md5-fc693aa157832059d7daeeb61c55 cddb:paid oder Betrag&paid verwenden (das ist kein Witz, ich kenne ein Paket, das & verwendet) oder was auch immer Sie bevorzugen. Aber auch wenn die Namen nur Konventionen sind: Es erleichtert die Kommunikation, wenn man sich an solche Konventionen hält. Sie haben viele Fragen zu tex.sx gestellt. Was werden Sie tun, wenn Sie ein Problem mit Ihrem Code haben, der im "persönlichen Stil" geschrieben ist? In den Standardstil übersetzen, eine Frage stellen und zurückübersetzen? Oder erwarten Sie, dass jeder mit Ihrem persönlichen Stil umgehen kann?

@eg9

Beim persönlichen Code darf man machen was man will

Sie würden dies nicht wissen, wenn Sie die Dokumentation lesen, ist alles, was ich sage.

Wenn Sie die Variable \f eines beliebigen Typs lokal definieren möchten, sollten Sie sich Sorgen machen, dass der Befehl von einem Paket definiert wird

Ich bin nicht einverstanden. Wenn sich Ihr Code in einem \group_begin: ... \group_end: befindet und Sie alle lokalen Variablen mit \<module>_clear_new:N und nur lokalen Variablen mit \<module>_set:N... zuweisen, brauchen Sie sich keine Sorgen zu machen Ihre lokalen Variablennamen kollidieren mit anderen Paketen, es sei denn, Ihr Code verwendet ein anderes Paket.

@u-fischer

Aber auch wenn die Namen nur Konventionen sind: Es erleichtert die Kommunikation, wenn man sich an solche Konventionen hält.

Ich sage nicht, dass es keine guten Gründe gibt, sich an die Konventionen zu halten. Ich sage nur, diese Konventionen sollten nicht zu Sprachregeln gemacht werden und die Dokumentation sollte klar zwischen Konventionen, für die die Begründung angegeben werden soll, und Regeln unterscheiden. Und die Entscheidung, ob die Konventionen befolgt werden, sollte letztendlich beim Programmierer liegen.

@EvanAad Sie müssen sich auch in dem von Ihnen beschriebenen Fall um Namenskonflikte kümmern. Sag, du schreibst

\cs_new_protected:Npn \evanaad_halve:n #1
  {
    \group_begin:
      \int_zero_new:N \f
      \int_set:Nn \f { (#1) / 2 }
      \iow_term:x { \int_use:N \f }
    \group_end:
  }

dann tut es ein Benutzer Ihres Pakets

 \int_const:Nn \f {123}
 \evenaad_halve:n { \f }

Sie werden überrascht sein, 0 und nicht 62 zu sehen.

Auf der anderen Seite, wenn Sie bei Namen wie \evanaad_f usw. (oder kürzer \@@_f usw. mit l3docstrip Magie) bleiben, sollten Sie auf der sicheren Seite sein.

Sie würden dies nicht wissen, wenn Sie die Dokumentation lesen, ist alles, was ich sage.

Entschuldigung, aber expl3.pdf verwendet das Wort "Konvention" ungefähr 20 Mal. Im Fall von öffentlichem versus privatem Befehl gibt es sogar den Satz "Es gibt (fast) keine Möglichkeit, dies ohne großen Rechenaufwand durchzusetzen, daher implementieren wir es nur durch eine Namenskonvention".

@blefloch Guter Punkt.

@u-fischer OK, fair genug. Was ist mit der Konvention, dass der Name einer Funktion mit einem Argumentspezifizierer enden sollte? Dies ist nicht ganz eine Konvention, da die Funktionen von Abschnitt 3.3 den Argumentspezifizierer untersuchen, aber diese Funktionen sind lediglich "syntaktischer Zucker", und wenn Sie sie nicht verwenden, gibt es kein Hindernis, Funktionsnamen wie \mymodule_myfunc , aber das wüsste man nicht aus der Anleitung.

Am 19. Oktober 2017 um 17:52 schrieb EvanAad [email protected] :

@u-fischer OK, fair genug. Was ist mit der Konvention, dass Funktionsnamen mit einem Argumentspezifizierer enden sollten? Dies ist nicht ganz eine Konvention, da die Funktionen von Abschnitt 3.3 den Argumentspezifizierer untersuchen, aber diese Funktionen sind nur "syntaktischer Zucker", und wenn Sie sie nicht verwenden, gibt es kein Hindernis, Funktionsnamen wie \mymodule_myfunc zu verwenden.

Das ist natürlich für cs_generate_variant :Nn notwendig.

Ciao
Enrico

Mit \mymodule_myfunc könnten Sie keine Funktion von verwenden
l3expan . Diese Erweiterungsfunktionen und der Variantenbegriff sind a
Kernteil von expl3.

Ich stimme zwar zu, dass Variablennamen kürzer gemacht werden können (Entfernen
"l_"/"g_" und "_int"/...), Funktionssignaturen sind wirklich nicht "nur a
Konvention".

@blefloch Ich

\ExplSyntaxOn
\cs_new:Npn \MyDocumentCommand {Hello,~world!}
\ExplSyntaxOff

und Sie müssen nicht zuerst eine "Schatten"-Funktion \mymodule_my_document_command: und dann mit kopieren

\cs_new_eq:NN \MyDocumentCommand \mymodule_my_document_command:

@blefloch Und neben \cs_generate_variant:Nn , das @eg9 erwähnte, verwenden andere Funktionen des Moduls l3expan den Argumentspezifiziererteil des Funktionsnamens?

für mich hört es sich mittlerweile so an, als würdest du hauptsächlich um des streitens willen argumentieren

ja du kannst das alles machen und am ende des tages die einzig harte sprache
Regeln sind das, was die TeX-Engine in ihren Primitiven fest verdrahtet. Und gegeben
dass TeX eine sich selbst modifizierende Sprache ist, von der aus Sie im Grunde überall hingehen können
dort zB

\endlinechar-1\def~#1{\catcode`#113}~Q~S~U~_~V~W~J~K~L~M~N~O~@~X~Y~[~] ~(
~|~&~Z~'~"~ ~h~z~:~q~j~k~;~/~)~!~,~$~+\let_\let_~newcount~$$-1~Q ~J~V~S~K~W~U~L~,~''1~""2~ *1_&\count&144'&155'&145"&154"_[\ifnum_(\ifcase_O\or
_|\else_]\fi_N\number_@\advance_X\expandafter_Z\global_Y\typeout_~newif
~\ifG~\if_~\def~j{[0 Q[0Jk|$]|$]|$]|$]}~k{&1NQNJ}~\2#1#2{}~:#1{

11#12#13#14#15#16#17#18}~h#1#2{#2:{~\q#1}~#2^^J}~\q#1#2{(&1 #1#2~~OO$]}

~/{Y{Zeile und Spalte? zB E6}\read$toM\ifcat~X\2M~$$X\jM|!input!]}~!#1!{
Y{Ungültiges #1.}/}~\j#1#2{Q #1@Q- @J #2@J- 0;(V!move!]}~;{V0 (jS1z1z0z{$} S
0z1z{$}S$z1z0z{$}]}~_{@,\ifodd'-]}~z#1{{\trueK#1{\falseq}}}~q{@ QS@JK [j="
\ifZk'Z_2]@V1q|[j='ZVV\ifG\if|\aftergroupq]]]}~\,#1{Q#1:.}~.#1{J#1;[0
WWVUQLJ]]}~+#1{(#1O2O-2O0O0O0O0O-2O2]}~){'X"X"N'Y{^^J:
~^^Jh1Ah2Bh3Ch4Dh5Eh6Fh7Gh8H :~^^J}\GfalseW(W$|0]~:\,\Gtrue[0 /];k'_1][$=WY{(,Unentschieden| Spieler [0>,.|$]~gewinnt mit N[0>,-],].}X\dump])}~~{ })

das ist ein schönes TeX-Dokument (eigentlich ein schönes LaTeX-Dokument)
aber was seinen Code betrifft, ist er überhaupt nicht sehr nützlich. Und
dass Bruno ein solches Dokument schreiben kann, heißt das nicht
das expl3-Handbuch (oder in diesem Fall ein LaTeX-Handbuch) sollte alles beschreiben.

LaTeX (2.09 und auch 2e) Code hatte das große Problem, dass in der Anfangszeit
zu viele Leute, die es programmiert haben, haben von Low-Level-Shortcuts verstanden
in TeX und benutzten und missbrauchten sie, weil sie dachten, dass es nicht so ist
schädlich. Als Ergebnis ist eine riesige Menge bestehender 2e-Pakete
nicht miteinander kompatibel oder haben bei der Verwendung stellenweise subtile Probleme
zusammen usw. oder ab und zu brechen, weil sie einen oder die anderen umgangen haben
Benutzeroberfläche (weil es anscheinend auch ohne funktionierte).

Sie bitten uns im Grunde immer wieder, genau das zu dokumentieren,
dh mögliche Abkürzungen, die nur die Designprinzipien verletzen
weil sie manchmal funktionieren (oder sogar im Moment immer). Aber expl3
und seine Konventionen/Regeln sind weitgehend aus der Erfahrung abgeleitet, dass
Programmierer haben sich in der Vergangenheit nicht an solche Regeln gehalten und das Chaos, das daraus resultiert
davon. Also nein, die Regeln sind bewusst und nicht nur Launen (die meisten
der Zeit) und obwohl "wenn du weißt was du tust, dann bist du
kann die meisten von ihnen in einer bestimmten Situation umgehen", heißt das nicht
Wenn du deinen Code dann von einem Ort zum nächsten verschiebst, wird das immer noch so sein
der Fall ist oder muss es im Laufe der Zeit der Fall sein.

Wie von anderen gesagt, gibt es einen großen Unterschied zwischen Code, auf dem Sie schreiben
die Fliege für dich selbst und Code schreibst du als "offiziell" verteilt
Paket. Zumindest für letzteres bitten wir um Akzeptanz der Regeln und
betrachten sie als Teil der Sprache. Für sich selbst möchten Sie vielleicht
lernen, wie man ein Dokument wie das obige codiert, aber das Wissen, wie es geht
das kommt nicht aus dem expl3-Handbuch


Trotzdem möchte ich Sie von anspruchsvollen Konzepten nicht abhalten,
Befehle, Schnittstellen, was hast du. Viele der Punkte, die Sie angesprochen haben
andere Gelegenheiten wurden gut angenommen (oder haben uns zumindest dazu gebracht, eine zu überdenken)
oder der andere Punkt).

Aber was das expl3-Handbuch betrifft, denke ich, was Sie gehört haben
mehreren Leuten ist, dass es kein Interesse gibt, die
„Nicht-Konventionen“ und die „Nicht-Regeln“. Außerdem, wenn der Code zu stark umleitet
von dem, was wir Regeln/Konventionen nennen, wird es immer noch TeX-Code sein, aber
kein expl3-Code mehr.

Ich denke, wir haben das hier durchgesprochen: Ich werde schließen, aber auf Wunsch natürlich wieder öffnen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen