6

I am trying to create a macro that creates two macros. The first sets a default value and the second creates a macro to redefine the first. I am trying to generalize a common pattern I am using quite a bit.

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

Usage:

\mkMac{affilation}
\affilation{University}
Welcome to \theaffilation
  • This has been asked before. Can you give some more context? – egreg Sep 3 '13 at 14:48
  • I added context. I searched for a similar question, but I couldn't find it. – Ra is dead Sep 3 '13 at 14:56
  • This may be relevant: tex.stackexchange.com/questions/109615/… – Steven B. Segletes Sep 3 '13 at 15:45
  • 1
    \the syntax is used for LaTeX counter and lengths so you would better off with a different prefix. – percusse Sep 3 '13 at 15:49
7

With \newcommand and \renewcommand you have to use \csname...\endcsname, with some \expandafter to build the control sequence before \newcommand or \renewcommand comes into action:

\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

This is the output on the terminal when running the example (\stop is just to end the run):

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.

So \mkMak{affiliation} defines a temporary value for \theaffiliation and the macro \affiliation; the call \affiliation{University} redefines \theaffiliation to University.

5

You can use etoolbox\csdef but in this case LaTeX won’t test if a macro is defined already.

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

Note that with \csdef the braces around the macro name are mandatory and the leading backslash must be omitted.

  • I think that \csdef{#1}##1{\csdef{#1}{##1}} should be \csdef{#1}##1{\csdef{the#1}{##1}} – Ra is dead Sep 3 '13 at 15:52
  • @Raisdead: You’re right. Didn’t test is since you din’t provide a MWE ;-) – Tobi Sep 3 '13 at 15:55
3

If you don’t want to think about expansion and want to use the functions of \newcommand, you can use the macros \csnewcommand and \recsnewcommand defined as

\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

This way you can use both the starred and un-starred version without \expandafter.

Code

\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}

Output

Welcome to “The macro affilation”.

Welcome to “University”.

1

The two-line solution which uses only TeX primitives follows:

\def\sdef#1{\expandafter\def\csname#1\endcsname}
\def\mkMac#1{\sdef{the#1}{The macro #1}\sdef{#1}##1{\sdef{the#1}{##1}}}

\mkMac{affilation}
\affilation{University}
Welcome to \theaffilation
  • Without any control whatsoever about the macro already having a definition. – egreg Nov 18 '14 at 10:33
  • We are using TeX and this is normal behavior of TeX. The question doesn't include explicitly the task about this more intelligence. But if somebody needs this, then my macro would have three lines no two lines. That is all. – wipet Nov 19 '14 at 7:26
0

LaTeX defines a short interface similar to that provided by etoolbox in the form of \@namedef (from latex.ltx):

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

Here is a minimal example showing the usage:

enter image description here

\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}
  • Without any control whatsoever about the macro already having a definition. This is essentially the same answer as Tobi's. – egreg Nov 18 '14 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.