我有一些乳胶代码,有点像这样:
% Sp defines a generic command for an arbitrary space,
% and all of the others just delegate the bulk of their
% work to it so that when I decide to change the formatting,
% I can in one place.
\newcommand{\Sp}[2]{\textrm{#1}\left(#2\right)}
\newcommand{\Nul}[1]{\Sp{Nul}{#1}}
\newcommand{\Col}[1]{\Sp{Col}{#1}}
\newcommand{\Row}[1]{\Sp{Row}{#1}}
% Some common vectors, so I don't have to repeatedly type
% \vec{x}_1:
\newcommand{\u}{\vec{u}}
\newcommand{\v}{\vec{v}}
\newcommand{\w}{\vec{w}}
\newcommand{\x}{\vec{x}}
\newcommand{\y}{\vec{y}}
我所做的工作是线性代数,我需要使用这些向量很多。因此,定义较短的命令似乎很自然。但是当论文开始变长时,我最终要么将字母表的一半定义为不同的命令——每个字母一个命令。
所以我尝试定义一个命令,该命令仅定义另一个命令,以便我可以将它放入循环中......
\newcommand{\MkVec}[1]{\expandafter\def\#1{\vec{#1}}}
以及由此产生的几种变化...但是我最接近工作模型的是当编译器给我的错误变为 时missing \begin{document}
。
有人能解释一下或提供资料来进一步了解我应该做什么(或者是否有更好的方法)来定义动态命令吗?请注意,这个特定实例只是一个例子。我对做 LaTeX 元编程感兴趣,而不是专门渲染矢量。
答案1
使用\#
简单的定义\#
。您需要一个东西,给定一个名称,它将成为具有该名称的命令。这样的东西作为 TeX 原始命令存在:\csname ... \endcsname
\documentclass{article}
\newcommand{\MkVec}[1]{\expandafter\def\csname#1\endcsname{\vec{#1}}}
\MkVec{x}\MkVec{y}
\begin{document}
Some vectors: $\x$, $\y$.
\end{document}
如果必须定义那么多向量,您可以考虑用粗体字母而不是 来表示它们\vec
。这样公式看起来就不会那么混乱。
答案2
为了补充 Dan 的回答,您可以执行以下操作\MkVec{..}
避免重复。
\newcommand{\MkVec}[1]{\expandafter\def\csname#1\endcsname{\vec{#1}}}
\def\lst{x,y,z,u,v,w,a,b,c}
\@for\i:=\lst\do{%
\expandafter\MkVec \i }
现在,通过此实现,您可以通过一个操作维护/修改相关宏的列表。如果您决定\x
应该表示其他含义,只需将其删除即可\lst
。(对我来说,\x
是\times
。)而添加新条目只需输入单个 leeters。在另一个场景中,假设您稍后决定宏应该真正称为\xvec
、\yvec
等。请这样做
\def\str{vec}
然后,在 的定义中,立即在 后\MkVec
添加。\str
#1
\newcommand{\MkVec}[1]{\expandafter\def\csname#1\str\endcsname{\vec{#1}}}
for 循环保持不变。
字符串#1
也可以添加在前面。因此,通过扩展,您可以生成微列表来替换定义页面,例如
\def\dx{\partial x}
\def\dy{\partial y}
\def\dz{\partial z}
\num\def\limx0{lim_(x->0)}
\num\def\limy0{lim_(y->0)}
\num\def\limz0{lim_(z->0)}
每个条目都必须单独维护。
但是,我用这种方法对希腊字母没有任何效果。
哦,你可能有兴趣这个包它使您可以在宏的字符串名称后添加数字。该包包含有关如何使用它的良好介绍,并为我们提供了使用 lateX 进行元编程的见解。
编辑:\ddix 和 \dix 等命令在 \MkVec 结构下确实会互相干扰。您需要在每个 \MkVec 类函数实例之后立即执行 for 循环。例如
\newcommand{\MKa}...
\newcommand{\Mkb}...
\@for...
\expandafter \MKa \i
\expandafter \MKb \i }
可能不起作用。但下面的方法可以。
\newcommand{\MKa}...
\@for...
\expandafter \MKa \i }
\newcommand{\Mkb}...
\@for...
\expandafter \MKb \i }
最后一件事。我觉得我需要为可能看到这个讨论的其他人添加这一点。要使用@
在文件中,需要\makeatletter
在使用前和\makeatother
使用完毕后包含。在包中,例如 .sty 文件,声明是可选的,应避免使用。