![\@namedef 和 \@nameuse 的正确用法](https://linux22.com/image/272920/%5C%40namedef%20%E5%92%8C%20%5C%40nameuse%20%E7%9A%84%E6%AD%A3%E7%A1%AE%E7%94%A8%E6%B3%95.png)
在一个上一个问题我问过如何循环生成多个保存框。答案围绕构建csname
,里面的部分csname
相当长,我需要多次使用名称(创建框、填充框、获取属性并使用它)。因此我想缩短它。我试过了
\makeatletter
...
\@namedef{saveBox}{<what was inbetween \csname \endcsname>}
...
\expandafter\newsavebox\@nameuse{saveBox}
...
\makeatother
这对我来说不起作用。如果能提供一些关于内部运作/一般用途的简短背景信息就更好了。
答案给我留下了一个问题,我无法让该\def
版本与直接版本一起工作,请参阅示例以获取说明:
\def\floatRow@currentSaveBox{floatRow@savebox\alph{floatRow@rowImageCount}}
%\expandafter\newsavebox\csname\floatRow@currentSaveBox\endcsname %works
\expandafter\newsavebox\csname{}floatRow@savebox\alph{floatRow@saveboxCount}\endcsname %gives mising number error
我认为我对\commandName
和 字符串的分离floatRow@savebox
是错误的。以下是 MWE:
\documentclass{report}
\begin{document}
\newcounter{c}
\def\currentSBox{prefix\alph{c}}
\expandafter\newsavebox\csname\currentSBox\endcsname
\expandafter\savebox\csname\currentSBox\endcsname{dummy}
\expandafter\usebox\csname\currentSBox\endcsname
\expandafter\usebox\csname{}prefix\alph{c}\endcsname
\end{document}
答案1
让我们看看这里发生了什么。构造
\@namedef{saveBox}{<what was inbetween \csname \endcsname>}
定义\saveBox
为带有替换文本的宏<what was inbetween \csname \endcsname>
。这是因为\@namedef
定义为
#1->\expandafter\def\csname #1\endcsname
这意味着它首先会将#1
(saveBox
在你的情况下)转换为控制序列(\saveBox
这里),然后应用\def
。因此,它变得与执行
\def\saveBox{<what was inbetween \csname \endcsname>}
这是一件很有用的事情,但在当前情况下实际上并不是您想要的!
第二行
\expandafter\newsavebox\@nameuse{saveBox}
会因为多种原因而严重失败,正如评论中提到的那样。\@nameuse
是一个包装器\csname ...\endcsname
,因此只需一次扩展就可以
\newsavebox\csname saveBox\endscsname
尝试将其定义\csname
为一个新的框!如果我们进行两次扩展,我们就会得到
\newsavebox\saveBox
这仍然是错误的,因为您已经将其定义\saveBox
为宏。
根据链接的问题,你似乎想要的是更多形式
\def\my@name{MyString\@alph\count@}
\expandafter\newsavebox\csname\my@name\endcsname
...
\expandafter\usebox\csname\my@name\endcsname
IE将名称的形式保存在宏中并重复使用。
您可能想知道它\@nameuse
有什么用处,因为它似乎使事情变得更加复杂而不是更简单(\@namedef
很方便)。这至少部分是历史原因:当编写 LaTex2e 时,标记非常“昂贵”,因此当您查看内核中的所有用途时,节省\@nameuse
(一个标记)而不是\csname ...\endcsname
(两个标记)是值得的。今天,这不再那么重要了,尽管有一种观点认为
\def\foo#1{% Some function
...
\@nameuse{my@#1}%
}
比
\def\foo#1{% Some function
...
\csname my@#1\endcsname
}
因为它表明某些东西正在被使用,而不是通过名称来定义。
使用\@namedef
更常见,因为它允许轻松构造“即时”名称。例如,我们可以想象存储一些用户输入:
\newcommand{\mycommand}[2]{%
\@namedef{mycommand@store@#1}{#2}%
}
这可能会被用来保存一些用户信息:我将使用电子邮件地址,但它可以是任何东西
\mycommand{Joe Bloggs}{[email protected]}
如果你有一个更大的设置来执行此操作,比如存储有关几个“键”的几条数据,那么使用\@namedef
比使用\expandafter\def\csname ...
\mycommand{AN Other}{[电子邮件保护]}