![试图理解 \@cdr...\@nil 与 \expandafter 的关系](https://linux22.com/image/338092/%E8%AF%95%E5%9B%BE%E7%90%86%E8%A7%A3%20%5C%40cdr...%5C%40nil%20%E4%B8%8E%20%5Cexpandafter%20%E7%9A%84%E5%85%B3%E7%B3%BB.png)
我正在尝试定义一个\@ifnextchars
带有三个参数的宏,第一个参数是字符列表,根据第一个参数的字符是否跟在命令后面,该宏将扩展为第二个或第三个参数。下面是我所做的以及我想如何使用它的一个简单示例。
\documentclass{article}
\makeatletter
\newcommand\@ifnextchars[3]{%
\expandafter\ifx\expandafter\@empty#1\@empty%
\def\@ifnextchars@tmp{#3}%
\else%
\def\@ifnextchars@tmp{%
\expandafter\expandafter\expandafter\@ifnextchars@aux\expandafter%
{\@car#1\@nil}{\@cdr#1\@nil}{#2}{#3}%
}%
\fi%
\@ifnextchars@tmp%
}
\newcommand\@ifnextchars@aux[4]{%
\expandafter\@ifnextchar#1{%
#3%
}{%
\@ifnextchars{#2}{#3}{#4}%
}%
}
\newcommand\whereinsentence{%
\@ifnextchars{.!?}{%
I am in the end of a sentence.
}{%
I am not in the end of a sentence.
}%
}
\newcommand\vowel{%
\@ifnextchars{aeiouy}{%
Vowel:
}{%
Not vowel:
}%
}
\makeatother
\begin{document}
Here is \whereinsentence a sentence\whereinsentence.
\vowel a.
\vowel b.
\end{document}
不幸的是,它不能编译:
Runaway argument?
{I am in the end of a sentence. }{\@ifnextchars {\@cdr \@cdr .!?\@nil \ETC.
! Paragraph ended before \@cdr was complete.
<to be read again>
\par
l.44
我猜是它\@cdr
在需要时没有扩展。我觉得这很奇怪,因为我确保\@cdr
用…扩展了我的\expandafter
……所以我猜我不太明白它是如何\expandafter
工作的 ☹ 有人能帮我吗?
我受到了这篇文章的启发:概括 \@ifnextchar 以考虑多个字符。
但是,最后这篇帖子是关于创建查找整个单词的变体\@ifnextchar
。我只是想知道给定的字符之一是否直接出现。
我已经这样做了,以确保不会与发生反应。我觉得这不太令人满意:如果有人有更好的解决方案,我很乐意接受\ifx
☺\def
\@ifnextchar
\fi
提前致谢。
答案1
您不能像这样扩展第二个参数。这里有一个借助 eTeX 的简单方法:
\documentclass{article}
\makeatletter
\newcommand\@ifnextchars[3]{%
\if\relax\detokenize{#1}\relax
\def\@ifnextchars@tmp{#3}%
\else
\edef\@ifnextchars@tmp{%
\noexpand\@ifnextchars@aux
{\unexpanded\expandafter{\@car#1\@nil}}
{\unexpanded\expandafter{\@cdr#1\@nil}}
\unexpanded{{#2}{#3}}%
}%
\fi
\@ifnextchars@tmp
}
\newcommand\@ifnextchars@aux[4]{%
\@ifnextchar{#1}{%
#3%
}{%
\@ifnextchars{#2}{#3}{#4}%
}%
}
\newcommand\whereinsentence{%
\@ifnextchars{.!?}{%
I am in the end of a sentence.
}{%
I am not in the end of a sentence.
}%
}
\newcommand\vowel{%
\@ifnextchars{aeiouy}{%
Vowel:
}{%
Not vowel:
}%
}
\makeatother
\begin{document}
Here is \whereinsentence a sentence\whereinsentence.
\vowel a.
\vowel b.
\end{document}
答案2
主要问题是您正在扩展\@car
,但没有扩展\@cdr
,因为 s 链\expandafter
未到达它。
expl3
这是一个您可能喜欢学习的实现。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_new_protected:Nn \bodin_ifnext_chars:nnnn
{
\tl_if_in:nnTF { #1 } { #2 } { #3 } { #4 } #2
}
\NewDocumentCommand{\ifnextchars}{mmmm}
{
\bodin_ifnext_chars:nnnn { #1 } { #4 } { #2 } { #3 }
}
\ExplSyntaxOff
\newcommand\whereinsentence{%
\ifnextchars{.!?}{%
``I am in the end of a sentence.''
}{%
``I am not in the end of a sentence.''
}%
}
\newcommand\vowel{%
\ifnextchars{aeiouy}{%
Vowel:
}{%
Not vowel:
}%
}
\begin{document}
Here is \whereinsentence a sentence\whereinsentence.
\vowel a.
\vowel b.
\end{document}