根据参数定义宏

根据参数定义宏

我正在尝试创建一个宏,该宏会创建两个宏。第一个宏设置默认值,第二个宏创建一个宏来重新定义第一个宏。我试图概括我经常使用的常见模式。

\newcommand{\mkMac}[1]{%
\newcommand{\the#1}{The macro ##1}
\newcommand{\#1}[1]{\renewcommand{\the#1}{##1}}
}

用法:

\mkMac{affilation}
\affilation{University}
Welcome to \theaffilation

答案1

使用\newcommand和,\renewcommand您必须使用\csname...\endcsname,以及一些在或生效\expandafter之前构建控制序列:\newcommand\renewcommand

\newcommand{\mkMac}[1]{%
  \expandafter\newcommand\csname the#1\endcsname{%
    Call the macro \texttt{\expandafter\string\csname #1\endcsname}!%
  }%
  \expandafter\newcommand\csname #1\endcsname[1]{%
    \expandafter\renewcommand\csname the#1\endcsname{##1}%
  }%
}

\mkMac{affiliation}
\show\theaffiliation
\show\affiliation
\affiliation{University}
\show\theaffiliation

\stop

这是运行示例时终端上的输出(\stop只是结束运行):

This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013)
 restricted \write18 enabled.
entering extended mode
(./mkmak.tex
LaTeX2e <2011/06/27>
Babel <3.9f> and hyphenation patterns for 78 languages loaded.
> \theaffiliation=\long macro:
->Call the macro \texttt {\expandafter \string \csname affiliation\endcsname }!.
l.11 \show\theaffiliation

?
> \affiliation=\long macro:
#1->\expandafter \renewcommand \csname theaffiliation\endcsname {#1}.
l.12 \show\affiliation

?
> \theaffiliation=\long macro:
->University.
l.14 \show\theaffiliation

?
 )
No pages of output.
Transcript written on mkmak.log.

因此为和宏\mkMak{affiliation}定义一个临时值;调用重新定义为。\theaffiliation\affiliation\affiliation{University}\theaffiliationUniversity

答案2

您可以使用etoolbox'\csdef但在这种情况下,LaTeX 不会测试宏是否已经定义。

\usepackage{etoolbox}
\newcommand{\mkMac}[1]{%
  \csdef{the#1}{The macro ##1}
  \csdef{#1}##1{\csdef{the#1}{##1}}
}

请注意,\csdef宏名两端的括号是必需的,并且必须省略前导反斜杠。

答案3

如果你不想考虑扩展,而想使用的功能\newcommand,你可以使用宏\csnewcommand\recsnewcommand定义为

\makeatletter
\newcommand*\csnewcommand{\@star@or@long\csnew@command}
\newcommand*\csnew@command[1]{\expandafter\new@command\csname#1\endcsname}
\newcommand*\recsnewcommand{\@star@or@long\recsnew@command}
\newcommand*\recsnew@command[1]{\expandafter\renew@command\csname#1\endcsname}
\makeatletter

这样,您就可以使用带星号和不带星号的版本\expandafter

代码

\documentclass{article}
\makeatletter
\newcommand*\csnewcommand{\@star@or@long\csnew@command}
\newcommand*\csnew@command[1]{\expandafter\new@command\csname#1\endcsname}
\newcommand*\recsnewcommand{\@star@or@long\recsnew@command}
\newcommand*\recsnew@command[1]{\expandafter\renew@command\csname#1\endcsname}
\makeatletter

\newcommand*{\mkMac}[1]{%
  \csnewcommand*{the#1}{The macro #1}%
  \csnewcommand*{#1}[1]{\recsnewcommand*{the#1}{##1}}}
  
\begin{document}
\mkMac{affilation}
Welcome to ``\theaffilation''.

\affilation{University}
Welcome to ``\theaffilation''.
\end{document}

输出

欢迎来到“宏联盟”。

欢迎来到“大学”。

答案4

LaTeX 定义了类似于以下提供的简短接口etoolbox形式为\@namedef(来自latex.ltx):

\def\@namedef#1{\expandafter\def\csname #1\endcsname}

这是一个展示用法的简单示例:

在此处输入图片描述

\documentclass{article}

\makeatletter
\newcommand*{\mkMac}[1]{%
  \@namedef{the#1}{The macro #1}%
  \@namedef{#1}##1{\@namedef{the#1}{##1}}}
\makeatother

\begin{document}
\mkMac{affilation}
Welcome to ``\theaffilation''.

\affilation{University}
Welcome to ``\theaffilation''.
\end{document}

相关内容