10

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. – A.Ellett May 3 '15 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 – gigabytes May 3 '15 at 14:38
6

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
| improve this answer | |
  • Thanks! Can I use \newcommand instead of \def inside \bgroup? – gigabytes May 3 '15 at 14:39
  • 1
    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. – barbara beeton May 3 '15 at 15:18
  • @barbarabeeton \suchthatb{} can be \undefined – touhami May 3 '15 at 15:23
  • @barbarabeeton Updated answer to reflect your suggestion. Thank you. – A.Ellett May 3 '15 at 15:28
  • 2
    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. – egreg May 3 '15 at 15:37
6

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

enter image description here

| improve this answer | |

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.