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
4
  • This has been asked before. Can you give some more context?
    – egreg
    Commented Sep 3, 2013 at 14:48
  • I added context. I searched for a similar question, but I couldn't find it.
    – Ra is dead
    Commented Sep 3, 2013 at 14:56
  • This may be relevant: tex.stackexchange.com/questions/109615/… Commented Sep 3, 2013 at 15:45
  • 1
    \the syntax is used for LaTeX counter and lengths so you would better off with a different prefix.
    – percusse
    Commented Sep 3, 2013 at 15:49

5 Answers 5

8

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.

2
  • I think that \csdef{#1}##1{\csdef{#1}{##1}} should be \csdef{#1}##1{\csdef{the#1}{##1}}
    – Ra is dead
    Commented Sep 3, 2013 at 15:52
  • @Raisdead: You’re right. Didn’t test is since you din’t provide a MWE ;-)
    – Tobi
    Commented Sep 3, 2013 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
2
  • Without any control whatsoever about the macro already having a definition.
    – egreg
    Commented Nov 18, 2014 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
    Commented Nov 19, 2014 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}
1
  • Without any control whatsoever about the macro already having a definition. This is essentially the same answer as Tobi's.
    – egreg
    Commented Nov 18, 2014 at 10:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .