Как сделать команду доступной внутри аргумента другой команды?

Как сделать команду доступной внутри аргумента другой команды?

Когда я определяю среду с помощью \newenvironment, я могу использовать newcommandвнутри части «before», чтобы сделать команды доступными для кода внутри среды.

Возможно ли это с помощью простых команд? Другими словами, можно ли сделать команду такой, чтобы в аргументе пользователь мог использовать макрос, который не определен снаружи?

Пример: предположим, я хочу закодировать команду \setдля набора определений математических множеств и хочу, \suchthatчтобы внутри нее использовалась команда, например:

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

Это просто, но я бы хотел, \suchthatчтобы команда была доступна только внутри аргумента \set.

решение1

Вы можете определить команду как

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

И это будет \suchthatдоступно внутри макроса.

Вы могли бы сделать это с помощью \bgroupи \egroup, но это создает подформулу с последствиями того, как обрабатывается интервал, если используется в математическом режиме. Здесь \begingroupи \endgroupлокализуют определение новых макросов. Вы можете использовать любой из следующих вариантов для определения локальной команды, \def, \edefи \newcommand.

Следуя предложению @barbarabeeto, вы могли бы сделать в своей преамбуле что-то вроде этого:

\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

Это намного лучше. В дополнение к причинам, которые предлагает barbarabeeto, это также позволит вашему макросу ---если вы того пожелаете --- определять или задавать значения, к которым вы, возможно, захотите получить доступ позже в документе. При таком \begingroup/\endgroupподходе их придется глобализовать, что может быть не тем, что вам нужно.

Гибридный подход может выглядеть так

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

решение2

Предложения А. Эллетта хороши, но с этим подходом связаны некоторые тонкости.

  1. Локализация определения с помощью \bgroupand \egroupплоха, поскольку \setмакрос явно используется в математическом режиме. Такая конструкция создала бы подформулу, в результате чего пробелы заморожены и не участвуют в растяжении и сжатии на линии; использование \begingroupand \endgroupне страдает от этой проблемы.

  2. Определение по умолчанию \suchthatдолжно быть дано в любом случае, поскольку вам может понадобиться \suchthatуказать заголовок раздела.

  3. Обе команды следует сделать надежными по одной и той же причине.

Вот реализация.

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

Вывод в терминале:

! 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

Выход

введите описание изображения здесь

Связанный контент