接着我昨天的问题(使用标记列表常量测试标记列表变量中的项目是否包含特殊字符) 以及 egreg 的简短讨论和回答,我最不希望的是下面的 MWE 返回匹配,但没有成功。我的语法有什么问题?
\documentclass{article}
% RN. 18 November 2018
%=======================
\usepackage[check-declarations,log-functions]{expl3}
\usepackage{xparse}
%-----------------------
\ExplSyntaxOn
\tl_new:N \l_rn_auxOne_tl
\tl_new:N \l_rn_auxTwo_tl
\NewDocumentCommand\myTestTokenlist{m}
{
\tl_set:Nn \l_rn_auxOne_tl {#1}
\tl_set:Nn \l_rn_auxTwo_tl {\char"23}
\textbf{\#1~argument~received:}~\tl_use:N \l_rn_auxOne_tl\\
\textbf{special~character:}~\tl_use:N \l_rn_auxTwo_tl\\
Compare~variables:~
\tl_if_eq:NNTF \l_rn_auxOne_tl \l_rn_auxTwo_tl
{\textbf{match}\\}
{\textbf{NO~match}\\}
}
\ExplSyntaxOff
%-----------------------
\begin{document}
\verb+\myTestTokenlist{\#}+\\
\myTestTokenlist{\#}
\verb+\myTestTokenlist{\$}+\\
\myTestTokenlist{\$}
\end{document}
答案1
正如解释的那样我的答案,\#
是通过 定义的\chardef
。因此,这样的标记是不可扩张。
如果在排版环境中使用,它将输出当前字体中与给定数字相对应的字符(十六进制0x23
或十进制 35 \#
)。如果在 TeX 寻找数字的地方使用,它将生成数字:测试\ifnum\#="23
将返回 true。
TeX 的 token 比较规则在本例中很明确:\#
和\char"23
是不同的 token 列表,原因有几个。首先,前者是一个 token 长度,后者是四个 token 长度。
您能执行\tl_set:Nx \l_rn_auxOne_tl {\#}
并\l_rn_auxOne_tl
与包含的标记列表进行比较\char"23
吗?可以,但测试将返回 false,因为\#
是不可扩展的,因此使用x
-expansion 对其不起作用。
您可以使用复合测试:
\bool_lazy_and:nnTF { \token_if_chardef_p:N \# } { \int_compare_p:n { \# = "23 } }
{Found \token_to_str:N \#}
{Not found \token_to_str:N \#}
例子。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\testtoken}{m}
{
\tl_if_single:nTF { #1 }
{% only one token
\rn_test_single:N #1
}
{
--several~tokens~given,~retry.--
}
}
\cs_new:Nn \rn_test_single:N
{
\bool_lazy_and:nnTF
{ \token_if_chardef_p:N #1 }
{ \int_compare_p:n { #1 = "23 } }
{ Found~\texttt{\token_to_str:N \#} }
{ Not~found~\texttt{\token_to_str:N \#} }
}
\ExplSyntaxOff
\begin{document}
\testtoken{abc}
\testtoken{#}
\testtoken{\%}
\testtoken{\#}
\end{document}
答案2
对我来说,不清楚你想要什么。
\documentclass{article}
\usepackage[check-declarations,log-functions]{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_rn_auxi_tl
\tl_new:N \l_rn_auxii_tl
\NewDocumentCommand \myTestTokenlist { m }
{
\tl_set:Nn \l_rn_auxi_tl {#1}
\tl_set:Nn \l_rn_auxii_tl {\#}
\textbf{\#1 ~ argument ~ received:} ~ \texttt{\tl_to_str:N \l_rn_auxi_tl} \\
\textbf{special ~ character:} ~ \texttt{\tl_to_str:N \l_rn_auxii_tl} \\
Compare ~ variables: ~
\tl_if_eq:NNTF \l_rn_auxi_tl \l_rn_auxii_tl
{ \textbf{match} \par }
{ \textbf{NO ~ match} \par }
}
\ExplSyntaxOff
\begin{document}
\verb+\myTestTokenlist{\#}+\\
\myTestTokenlist{\#}
\verb+\myTestTokenlist{\$}+\\
\myTestTokenlist{\$}
\end{document}
如果你想比较\#
某样东西,就把它与 进行比较\#
,我不知道你为什么写成\char"23
,这显然是不同的。你的程序比较了 token 列表有,并不是这样输出等同的东西。
如果你想比较,#
你可以,但你需要考虑到,在命令定义中,你必须将#
s 加倍。这样就可以了:
\tl_set:Nn \l_rn_auxi_tl {#}
\tl_set:Nn \l_rn_auxii_tl {#}
\tl_if_eq:NNTF \l_rn_auxi_tl \l_rn_auxii_tl
{ match }
{ no ~ match }
但由于您处于宏定义中,因此需要将##
\NewDocumentCommand \testtokenlist { m }
{
\tl_set:Nn \l_rn_auxi_tl {#1}
\tl_set:Nn \l_rn_auxii_tl {##}
\tl_if_eq:NNTF \l_rn_auxi_tl \l_rn_auxii_tl
{ match }
{ no ~ match }
}
进而\testtokenlist{#}
。
但你应该解释一下你想要什么,因为我在这里看不到精确的逻辑。也许你应该考虑\str_if_eq:
而不是\tl_if_eq:
?