我想定义一个命令,该命令返回一个与 一起使用的标签\ref
,但它需要使用 \edef 来扩展另一个命令。但是,我遇到了几个以 开头的错误,这些错误来自Missing \endcsname inserted.
以下 M(not)WE:
\documentclass{article}
\begin{document}
\begin{equation}
\label{eq:test-10}
A=B
\end{equation}
\def\test#1{%
\edef\arg{test}%
\arg-#1}
This works \test{10}. But this doesn't \ref{eq:\test{10}}.
\end{document}
我也尝试过
\ref\expandafter{eq:\test{10}}
,但结果出现了错误
File ended while scanning use of \@setref.
我显然误解了有关扩展的一些基本知识,有人可以解释一下吗?有办法解决吗?
编辑:正如回复者所问,这是我的(不是那么简单的)用例。获取标签的命令有点复杂
\documentclass{article}
\makeatletter
\def\mytest#1{\@mytest#1--\relax}
\def\@stripdashes#1-#2\relax{#1}
\def\@mytest#1-#2-#3\relax{%
\edef\@arg@third{\@stripdashes#3-\relax}%
\ifx\@arg@third\empty%
% No year
\if\relax\detokenize{#2}\relax%
% No month
ONE-TWO-#1%
\else%
ONE-#1-#2%
\fi%
\else#1-#2-\@arg@third\fi%
}
\makeatother
\begin{document}
\begin{equation}
\label{eq:ONE-TWO-3}
A=B
\end{equation}
This works: \mytest{3}, \mytest{TWO-3}
But not this:
\ref{\mytest{3}}, \ref{\mytest{TWO-3}}
\end{document}
实际上,ONE 和 TWO 是动态构建标签的其他命令。
答案1
当 LaTeX 处理时,\ref{foo}
它基本上会查看控制序列是否\r@foo
被定义(用@
字母),并且为了做到这一点,它会执行
\csname r@foo\endcsname
里面的标记\csname...\endcsname
必须扩展为字符标记。在你的情况下,LaTeX 会尝试
\csname r@eq:\test{10}\endcsname
并\test
扩大到
\csname r@eq:\edef\arg{10}\endcsname
这是违法的。你不能在里面执行宏定义\csname...\endcsname
,确实,Missing \endcsname
只要\edef
扫描到,你就会得到结果。TeX 现在尝试通过\endcsname
在有问题的标记前面插入来恢复,但显然这会导致其他实际上毫无意义的错误。
对于您的用例(在我给出上述答案后解释),定义\@test
为四參數。
\documentclass{article}
\makeatletter
\def\mytest#1{eq:\@mytest#1---\@nil}
\def\@mytest#1-#2-#3-#4\@nil{%
\if\relax\detokenize{#3}\relax
% No year
\if\relax\detokenize{#2}\relax
% No month
ONE-TWO-#1%
\else
ONE-#1-#2%
\fi
\else
#1-#2-#3%
\fi
}
\makeatother
\begin{document}
\begin{equation}
\label{eq:ONE-TWO-3}
A=B
\end{equation}
This works: \mytest{3}, \mytest{TWO-3}, \mytest{ONE-TWO-3}
But not this:
\ref{\mytest{3}}, \ref{\mytest{TWO-3}}, \ref{\mytest{ONE-TWO-3}}
\end{document}
答案2
该参数需要扩展为标签名称,因此删除分配:
\documentclass{article}
\begin{document}
\begin{equation}
\label{eq:test-10}
A=B
\end{equation}
\def\test#1{%
test-#1}
This works \test{10}. But this doesn't \ref{eq:\test{10}}.
\end{document}
以上工作如预期。
这里没有什么特别的\ref
;例如,你会看到同样的失败
\setcounter{section}{\def\tmp{2}\tmp}
或者
\setcounter{\def\tmp{section}\tmp}{2}
\setcounter
需要扩展到计数器名称和<number>
但分配到的参数随后\tmp
扩展\tmp
可能打印作为部分名称或数字(或标签名称),但它不能通过扩展来发挥作用。
稍后添加到问题的扩展版本是类似的,您只需要使用可扩展测试,就像#3
您已经做的那样#1
(更复杂的情况可以使用\expanded
(或 expl3e
参数)而不是\edef
(expl3x
参数),但这里根本不需要。
\documentclass{article}
\makeatletter
\def\mytest#1{\@mytest#1---\relax}
\def\@mytest#1-#2-#3-#4\relax{%
eq:% missing from example in question here or in the `\ref`
\if\relax\detokenize{#3}\relax
% No year
\if\relax\detokenize{#2}\relax
% No month
ONE-TWO-#1%
\else%
ONE-#1-#2%
\fi%
\else#1-#2-#3%
\fi
}
\makeatother
\begin{document}
\begin{equation}
\label{eq:ONE-TWO-3}
A=B
\end{equation}
This works: \mytest{3}, \mytest{TWO-3}
But not this:
\ref{\mytest{3}}, \ref{\mytest{TWO-3}}
\end{document}