
Когда я определяю среду с помощью \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
Предложения А. Эллетта хороши, но с этим подходом связаны некоторые тонкости.
Локализация определения с помощью
\bgroup
and\egroup
плоха, поскольку\set
макрос явно используется в математическом режиме. Такая конструкция создала бы подформулу, в результате чего пробелы заморожены и не участвуют в растяжении и сжатии на линии; использование\begingroup
and\endgroup
не страдает от этой проблемы.Определение по умолчанию
\suchthat
должно быть дано в любом случае, поскольку вам может понадобиться\suchthat
указать заголовок раздела.Обе команды следует сделать надежными по одной и той же причине.
Вот реализация.
\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
Выход