\uppercase/\lowercase에 영향을 받지 않고 \outer 측면에서 (재)정의할 수 없는 토큰이 있습니까?

\uppercase/\lowercase에 영향을 받지 않고 \outer 측면에서 (재)정의할 수 없는 토큰이 있습니까?

\uppercase/ 에 영향을 받지 \lowercase않고 에 대해 (재)정의할 수 없는 토큰이 있습니까 \outer?

\uppercase(그렇다면 / 안에 사용할 수 있는 항목에 대해 인수 구분 기호로 사용하고 싶습니다 \lowercase.)

답변1

Afaik 해당 토큰이 없습니다.

각 토큰은 다음 두 가지 토큰 클래스 중 하나 이상에 속합니다. 활성 캐릭터 토큰은 두 클래스에 동시에 속합니다.

  1. 제어 순서. (제어 단어 토큰, 제어 기호 토큰, 활성 문자 토큰.) 모든 제어 시퀀스는 \outer.
  2. 명시적 문자 토큰. 각 명시적 문자 토큰은 \uppercase/ 에 의해 영향을 받을 수 있습니다 \lowercase( \uccode/ 가 \lccode적절하게 설정된 경우).

대부분의 경우 무제한 인수를 사용하고 비어 있는지 확인함으로써 구분된 인수를 완전히 피할 수 있습니다.

예를 들어 중괄호 균형 토큰 목록에서 첫 번째 무제한 인수를 추출하기 위해 나는 종종 다음과 같은 것을 사용합니다.

%%   \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@CheckWhetherNull다음과 같이 정의됩니다.

%%-----------------------------------------------------------------------------
%% 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}%
}%

또는

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

. )

이를 통해 다음을 얻을 수 있습니다.

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

구분되지 않은 첫 번째 인수를 제외한 모든 항목을 제거하는 데 필요한 반복 횟수를 줄이기 위해 로 구분된 인수를 사용했습니다 \UD@SelDOm. (필요한 반복 횟수는 " \UD@SelDOm중괄호 안에 중첩되지 않은 인수 내 횟수"+1입니다.)

\UD@SelDOm로 정의된 -delimiter가 마음에 들지 않으면 \outer다음과 같이 하지 않고 수행할 수 있습니다. 단, 결과를 얻을 때까지 더 많은 반복이 필요합니다. 필요한 반복 횟수는 다음과 같습니다. 자신이 중괄호 안에 중첩되지 않은 인수 내에서"+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}}%
}%

예:

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

구분된 인수를 완전히 피하기 위해 유사한 작업을 수행할 수 있는 상황이 많이 있습니다.


때때로 사람들은 문제의 인수를 처리하는 매크로 토큰을 인수 구분 기호로 사용합니다(예: ) \def\macro#1\macro{...}. 이것이 실현 가능/합리적인지 여부는 \macro자체 인수 내에 중첩되어 구분 기호를 잘못 일치시킬 수 있는지 또는 이와 유사한 일이 \let\macrob=\macro \outer\def\macro...발생할 수 있는지 여부 에 대한 질문에 따라 달라집니다 .



\outer\def...매크로 인수를 안전하게 만드는 방법에 대해 이미 생각하고 있으므로 및 \uppercase/ 외에 다른 함정이 있다는 점에 주목하고 싶습니다 \lowercase.

  1. 예를 들어 사용자가 제공한 (거의) 임의의 인수를 처리하는 구분된 인수를 기반으로 하는 매크로 메커니즘이 테이블 형식 환경/정렬 내에서 작동해야 하는지 여부에 대한 질문입니다.

    예를 들어 구분된 인수를 처리 \grabdelimited하고 사용자가 문자를 수집하고 토큰화 해제하는 데 사용하는 매크로를 가정합니다 B.&

    \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}
    

    tabular-environment 내부의 첫 번째/주석 처리된 줄은 오류를 생성하지만, 두 번째 줄은 여기서 &구분된 인수에 속하는 것이 중괄호 안에 숨겨져 있기 때문에 오류가 발생하지 않습니다 \@firstofone.

  2. 또 다른 문제는 불균형한 인수를 처리하는 매크로 정의에서 발생하는 일부와 잘못 일치할 수 있는 매크로 인수를 \if.../ \else/ 전달하는 것일 수 있습니다.\fi\if...\else

    \csname불균형 / 과 동일합니다 \endcsname.

답변2

확장된 설명:

인수 끝 표시가 \uppercase/ 의 영향을 받을까 두려운 경우에는 또는 \lowercase에서 볼 수 없도록 최상위 수준에 표시되지 않도록 해야 합니다 . 이는 확장 컨텍스트를 사용하는 등 확장이 중간에 멈출 수 없는 컨텍스트에만 삽입되도록 함으로써 달성할 수 있습니다 . 다음은 문자를 인수 끝 표시로 사용하는 매크로를 설정 하지만 더 확장되므로 입력 스트림에 표시가 남아 있지 않아 또는 의 영향을 받을 수 없습니다 .\uppercase\lowercase\romannumeralD\lowercase\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}

그런 다음 \mymacro@b확장 가능한 방식으로 인수를 처리하고 D구분 기호로 사용할 수 있습니다. 그리고 \romannumeral확장 컨텍스트를 \z@. 물론 \mymacro한 번 확장한 다음 시작하지 않고 확장 \mymacro@a하여 (with ) 의 영향을 받을 수 있지만 적어도 지금은 악의적인 의도로 생성해야 합니다.\expandafter\romannumeralD\lowercase\expandafter\expandafter\expandafter\lowercase\expandafter\expandafter\expandafter{\expandafter\expandafter\mymacro{}}

재정의 로부터 자신을 보호할 수는 없지만 \outer다른 사람의 코드 내부를 재정의하는 사람들은 \outer작동하는 코드를 원하지 않는 것 같으므로 자신을 보호해야 할 경우는 아닐 수도 있습니다.

관련 정보