How can I make a command available inside another command's argument?

When I define an environment with \newenvironment, I can use newcommand inside the "before" part, to make commands available to the code inside the environment.

Is this possible with simple commands? In other words, can I make a command such that into the argument the user can use a macro that is not defined outside?

Example: suppose I want to code a command \set to typeset mathematical sets definitions and I want a \suchthat command to be used inside, as in:

\set{x\in X \suchthat x > 42}


This is easy, but I'd like the \suchthat command to only be available inside an argument of \set.

• Yes you can do this. May 3, 2015 at 14:37
• If it was a funny way to say that I should edit the title to "How can I" instead of only "Can I", then thanks, I'll edit the title :P May 3, 2015 at 14:38

You can define a command as

\newcommand\set[1]{%%
\begingroup
\def\suchthat{... some definition...}%%
... other macro content ....
\endgroup}


And this will make \suchthat available inside the macro.

You could have done this with \bgroup and \egroup, but that creates a subformula with consequences on how the spacing is handling if used in math mode. The \begingroup and \endgroup here localize the definition of new macros. You can use any of the following to define a local command, \def, \edef, and \newcommand.

Following the suggestion of @barbarabeeto you could do something like this in your preamble:

\makeatletter
\def\ae@suchthat{... definition of such that ...}
\newcommand\aset[1]{%%
\let\suchthat\ae@suchthat
the body of the macro: #1
\let\suchthat\undefined
}
\makeatother


This is much better. In addition to the reasons that barbarabeeto suggests, this would also allow your macro---should you so wish---to define or set values that you may want to access later in the document. With the \begingroup/\endgroup approach, those would have to be globalized, which might not be what you'd want.

A hybrid approach could look like

\makeatletter
\def\ae@suchthat{... definition of such that ...}
\newcommand\aset[1]{%%
\begingroup
\let\suchthat\ae@suchthat
the body of the macro: #1
\endgroup
}
\makeatother

• Thanks! Can I use \newcommand instead of \def inside \bgroup? May 3, 2015 at 14:39
• this will result in repeated definitions of \suchthat -- once every time \set is used. it would be better to make two definitions at "base" level: \suchthata{... real definition ...} and \suchthatb{}, and then within \set, at the beginning \let\suchthat\suchthata and at the end disable it with \let\suchthat\suchthatb. this doesn't make \suchthat invalid, so it would probably be better to define \suchthatb to produce an error or at least a warning message. May 3, 2015 at 15:18
• @barbarabeeton \suchthatb{} can be \undefined May 3, 2015 at 15:23
• @barbarabeeton Updated answer to reflect your suggestion. Thank you. May 3, 2015 at 15:28
• I'd go with the first suggestion with grouping together with \let, so no “undefine” is necessary; however, \begingroup and \endgroup are necessary here, because \bgroup and \egroup will make a subformula if used in math mode, with nefarious consequences with regard to spacing: the spaces in the subformula are frozen. May 3, 2015 at 15:37

A. Ellett's suggestions are good, but there are some subtleties connected with this approach.

1. Localizing the definition with \bgroup and \egroup is bad, because the \set macro is clearly used in math mode. Such a construction would make a subformula, with the consequence that spaces are frozen and don't participate with stretching and shrinking on the line; using \begingroup and \endgroup doesn't suffer from this problem.

2. A default definition of \suchthat must be given anyway, because you can happen to want \suchthat in a section title.

3. Both commands should be made robust, for the same reason.

Here's an implementation.

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\newrobustcmd{\suchthat}{%
\@latex@error{Use \noexpand\suchthat only in \string\set}
{You are allowed to use \noexpand\suchthat only in the\MessageBreak
argument of \string\set}%
}
\newcommand\giga@suchthat{\mid}
\newrobustcmd{\set}[1]{%
\begingroup
\let\suchthat\giga@suchthat
\{\,#1\,\}%
\endgroup
}
\makeatother

\begin{document}

\tableofcontents

\section{The set $\set{x\in X \suchthat x>42}$}

Let's study $\set{x\in X \suchthat x>42}$.

\suchthat

\end{document}


The output in the terminal:

! LaTeX Error: Use \suchthat only in \set.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
...

l.27 \suchthat

? h
You are allowed to use \suchthat only in the
argument of \set


The output