LaTeX 的 \@ifnextchar 问题

LaTeX 的 \@ifnextchar 问题

我想构造一个命令,比如说\newlet,我可以用它来做

\newlet\x\y

和/或

\newlet\x=\y

\x唯一的(即尚未使用)。

开始了

\protected\def\newlet#1{%
  \@ifnextchar={\@firstoftwo{\@newlet{#1}}}{\@newlet{#1}}%
}
\def\@newlet#1{\@ifdefinable{#1}\relax\let#1= }

% Obviously works:
\newlet\sptoken=\@sptoken

% Obviously fails:
\newlet\sptoken\@sptoken

答案1

以一般方式处理空格很棘手。这里你需要一个预览和删除函数。这在 LaTeX3 中可用\peek_meaning_remove:NTF,即 ,其中我会使用

\RequirePackage{expl3}
\ExplSyntaxOn
\cs_new_protected:Npn \newlet #1
  {
    \peek_meaning_remove:NTF =
      { \cs_new_eq:NN #1 }
      { \cs_new_eq:NN #1 }
  }
\ExplSyntaxOff
\makeatletter
\newlet\sptoken=\@sptoken

当然,这可以用原语“写出”。忽略对标记的谨慎&(使用附录 D 技巧),类似

\makeatletter
\protected\long\def\newlet#1{%
  \protected\def\@newlet@fcommon{%
    \ifdefined#1%
      \expandafter\ERROR
    \fi
    \let#1= 
  }%
  \let\@tempa= =%
  \futurelet\@let@token\@newlet
}
\protected\def\@newlet{%
  \ifx\@let@token\@tempa
    \expandafter\@newlet@true
  \else
    \expandafter\@newlet@fcommon
  \fi
}
\protected\def\@newlet@true{%
    \afterassignment\@newlet@fcommon
    \let\@temp@= %
}

将会起作用(它是 的简化版本,\peek_meaning_remove:NTF分支是硬编码的)。特别要注意的是,=使用 和 来删除\let\afterassignment重新获得控制权,而不是使用参数。

这里的基本思想与 并无二致\@ifnextchar,但不包括后者所包含的删除空格的循环。LaTeX3 包提供了“预打包”的两者(相当于\@ifnextchar`\peek_meaning_remove_spaces:NTF)。

答案2

以下是约瑟夫赖特 (Joseph Wright) 想法的一个变体:

\protected\long\def\newlet#1{%
  \def\@newlet##1{%
    \ifdefined#1%
      \@latex@error{Command '\string#1' already exists}\@ehc
    \fi
    \let#1=
  }%
  \futurelet\@let@token\@@newlet
}
\protected\def\@@newlet{%
  \ifx\@let@token=%
    \expandafter\@newlet
  \else
    \expandafter\@newlet\expandafter\relax
  \fi
}

但它仍然失败了

\def\z#1{\newlet\y#1}\z{ }=\z

相关内容