Gibt es ein Token, das nicht durch \uppercase/\lowercase beeinflusst werden kann und nicht in Bezug auf \outer (neu) definiert werden kann?

Gibt es ein Token, das nicht durch \uppercase/\lowercase beeinflusst werden kann und nicht in Bezug auf \outer (neu) definiert werden kann?

Gibt es ein Token, das nicht durch \uppercase/ beeinflusst \lowercaseund in Bezug auf nicht (neu) definierbar ist \outer?

(Wenn ja, würde ich es gerne als Argumenttrennzeichen für Dinge verwenden, die innerhalb von \uppercase/ verwendet werden können \lowercase.)

Antwort1

Soweit ich weiß, gibt es kein solches Token:

Jeder Token gehört zu mindestens einer der folgenden beiden Token-Klassen – aktive Charakter-Token gehören zu beiden Klassen gleichzeitig:

  1. Steuersequenzen. (Steuerwort-Token, Steuersymbol-Token, aktive Zeichen-Token.) Alle Steuersequenzen sind hinsichtlich (neu)definierbar \outer.
  2. Explizite Zeichentoken. Jedes explizite Zeichentoken kann durch \uppercase/ beeinflusst werden \lowercase(vorausgesetzt, sein \uccode/ \lccodeist entsprechend gesetzt).

In vielen Situationen können Sie durch Trennzeichen gekennzeichnete Argumente vollständig vermeiden, indem Sie stattdessen mit durch Trennzeichen gekennzeichneten Argumenten arbeiten und eine Prüfung auf Leerheit durchführen.

Um beispielsweise das erste unbegrenzte Argument aus einer durch Klammern ausgeglichenen Token-Liste zu extrahieren, verwende ich oft so etwas wie das hier:

%%   \romannumeral\UD@ExtractFirstArgLoop{<argument>\UD@SelDOm}%
%%   yields <argument>'s 1st undlimited argument.
%%   <argument> must not be blank, i.e., must neither be empty nor consist
%%   only of explicit character tokens of catcode 10 and charcode 32.
%%
%%   \UD@SelDOm must not be defined in terms of \outer !
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%

( \UD@CheckWhetherNulldefiniert als

%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\z@\@secondoftwo}%
  {\expandafter\z@\@firstoftwo}%
}%

oder als

\newcommand\UD@CheckWhetherNull[1]{%
  \romanumeral\ifcat$\detokenize{#1}$%
  \expandafter\expandafter\expandafter\z@\expandafter\@firstoftwo\else
  \expandafter\expandafter\expandafter\z@\expandafter\@secondoftwo\fi
}%

. )

Damit erhalten Sie:

\romannumeral\UD@ExtractFirstArgLoop{{A}{B}CDE\UD@SelDOm}%A.

Um die Anzahl der Iterationen zu verringern, die zum Entfernen von allem außer dem ersten nicht abgegrenzten Argument erforderlich sind, habe ich ein durch abgegrenztes Argument verwendet \UD@SelDOm. (Die Anzahl der erforderlichen Iterationen ist: „Anzahl der \UD@SelDOmnicht in Klammern verschachtelten Argumente innerhalb des Arguments“ + 1).

\UD@SelDOmWenn Ihnen das -Trennzeichen, wie es möglicherweise in Bezug auf definiert ist , nicht gefällt \outer, können Sie wie folgt darauf verzichten – allerdings sind dann mehr Iterationen erforderlich, bis das Ergebnis vorliegt. Die Anzahl der erforderlichen Iterationen lautet: „Anzahl der nicht getrennten Argumente innerhalb des Arguments, die selbst nicht in Klammern verschachtelt sind“ + 1:

% Syntax now is: \romannumeral\UD@ExtractFirstArgLoop{<argument>{}}%
\newcommand\UD@GrabFirst[2]{{#1}}%
\renewcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@GrabFirst#1}}%
}%

Z.B,

\romannumeral\UD@ExtractFirstArgLoop{{A}{BC}DE{}}%A

Es gibt viele Situationen, in denen Sie ähnliche Dinge tun können, um abgegrenzte Argumente vollständig zu vermeiden.


Manchmal wird als Argumenttrennzeichen das Makro-Token verwendet, das das betreffende Argument verarbeitet, z. B. \def\macro#1\macro{...}. Ob dies möglich/sinnvoll ist, hängt von der Frage ab, ob es \macroin seinem eigenen Argument verschachtelt sein und dadurch das Trennzeichen fälschlicherweise zuordnen könnte oder ob so etwas \let\macrob=\macro \outer\def\macro...passieren könnte.



Da Sie bereits über die Frage nachdenken, wie Makroargumente sicher gemacht werden können, möchte ich darauf hinweisen, dass es neben \outer\def...und \uppercase/ noch weitere Fallen gibt \lowercase:

  1. Beispielsweise die Frage, ob ein auf abgegrenzten Argumenten basierender Makromechanismus, der (fast) beliebige vom Benutzer angegebene Argumente verarbeiten soll, in einer tabellarischen Umgebung/innerhalb einer Ausrichtung funktionieren sollte.

    Nehmen wir beispielsweise ein Makro an, \grabdelimiteddas ein abgegrenztes Argument verarbeitet und das der Benutzer zum Sammeln und Detokenisieren der Zeichen Bund verwendet &.

    \documentclass{article}
    \def\grabdelimited#1\delimiter{Arguments grabbed: \detokenize{#1}}%
    \begin{document}
    \grabdelimited B&\delimiter
    
    \makeatletter
    \begin{tabular}{|l|l|}
    %A&\relax\grabdelimited B&\delimiter\\
    A&\relax\expandafter\@firstofone\expandafter{\grabdelimited B&\delimiter}
    \end{tabular}
    \end{document}
    

    Die erste/kommentierte Zeile innerhalb der tabellarischen Umgebung würde einen Fehler ergeben, die zweite nicht, da hier die &Zugehörigkeit zum abgegrenzten Argument innerhalb der geschweiften Klammern von verborgen ist \@firstofone.

  2. Ein weiteres Problem könnte die Übergabe unausgeglichener \if.../ \else/ \fials Makroargumente sein, die fälschlicherweise mit einigen \if.../ übereinstimmen \else, die in den Definitionen der Makros vorkommen, die diese Argumente verarbeiten.

    Dasselbe gilt für unausgeglichenes \csname/ \endcsname.

Antwort2

Erweiterter Kommentar:

Wenn Sie wirklich Angst haben, dass Ihr Argumentende-Marker von \uppercase/ beeinflusst werden könnte \lowercase, müssen Sie nur sicherstellen, dass er nicht auf der obersten Ebene erscheint, sodass er nie von \uppercaseoder gesehen wird \lowercase. Dies könnte erreicht werden, indem sichergestellt wird, dass er nur in einem Kontext eingefügt wird, in dem die Erweiterung nicht dazwischen angehalten werden kann, z. B. durch Verwendung eines \romannumeralErweiterungskontexts. Das Folgende richtet ein Makro ein, das das Zeichen Dals Argumentende-Marker verwendet, aber da es weiter erweitert, bleibt dieser Marker nie im Eingabestrom, sodass er von \lowercaseoder beeinflusst werden könnte \uppercase:

% first insert a \romannumeral such that the following is expanded as far as possible
\newcommand*\mymacro{\romannumeral\mymacro@a}
% only after \romannumeral has started input the delimiter
\newcommand\mymacro@a[1]{\mymacro@b #1D}

Dann \mymacro@bkönnte das Argument erweiterbar verarbeitet und Dals Trennzeichen verwendet werden. Und Sie könnten den \romannumeralErweiterungskontext mit beenden \z@. Natürlich könnten Sie immer noch \mymacroeinmal erweitern und dann \mymacro@amit erweitern, \expandafterohne zu beginnen \romannumeral, sodass (mit ) Dbeeinflusst werden könnte , aber zumindest muss dies jetzt mit böswilliger Absicht erstellt werden.\lowercase\expandafter\expandafter\expandafter\lowercase\expandafter\expandafter\expandafter{\expandafter\expandafter\mymacro{}}

Sie können sich nie vor einer \outerNeudefinition schützen, aber Leute, die interne Teile des Codes anderer Leute neu definieren, \outerwollen offenbar keinen funktionierenden Code haben. Daher ist dies vielleicht kein Fall, vor dem Sie sich schützen müssen.

verwandte Informationen