在法国,我们通常将开区间或半开区间写为
]a,b[
或[a,b[
,而不是(a,b)
或[a,b)
。我尤其不喜欢,(a,b)
因为它可能与有序对混淆。因此,我定义了一个\interv
命令,以便\interv]a,b[
例如在 中]
被视为开始分隔符和结束分隔符。和[
之间的逗号也可以用另一个符号替换或用更多空格包围,以避免与小数分隔符混淆,特别是如果逗号声明为。a
b
\mathord
我知道我可以简单地为四个可能的间隔定义一个不同的命令,但这并不好玩。主要的困难是找到逗号后的结束分隔符,因为它可以是]
或[
。我知道答案如何读取最多两个不同分隔符之一的标记流但似乎并不能解决我的问题。我的解决方案(见下文)是测试逗号后的每个标记,看看它是否是]
或[
。括号分隔的标记列表中的分隔符和逗号将被忽略。
我还允许\lr
在\interv
和 之间放置 开始分隔符:这会分别在左分隔符和右分隔符之前插入\left
和。另一种可能性是放置( ,等) 命令之一来代替:这会分别在左分隔符和右分隔符之前插入和,等。\right
\big
\Big
\lr
\bigl
\bigr
除了在分段命令和目录中,这种方法效果很好,而且只有在使用\lr
或时才有效。由于在定义中,\big
简单的方法在所有情况下都有效,但我该怎么做才能让和在中也能工作\interv]a,b[
\protect
\interv
\interv\lr]a,b[
\inter\big]a,b[
\section
?我的命令很麻烦,所以请随意建议完全不同的解决方案,但对用户来说语法相同!
这是我的代码:
\documentclass{article}
\makeatletter
% Main routine.
% Examples of use:
% -- "\interv[a,b]", where "," is replaced by "\intervsep";
% -- "\interv]-a,b[", where "]" is replaced by "\mathopen]" and "[" by
% "\mathclose[";
% -- "\interv\lr]a,b]", where the left "]" is replaced by "\left]" and the
% right one by "\right]";
% -- "\interv\Bigg[a,b[", where the left "[" is replaced by "\Biggl[" and the
% right one by "\Biggr[".
% -- "\interv[a,{f[x]}]", to hide brackets inside the braces so that the closing
% delimiter is the uttermost right "]".
\def\interv{\tok@list={}%
\protect\interv@I}
% Define the symbol and the spacing between <a> and <b>.
% Note: "\mathopen{}" is put after "\intervsep" in "\interv@V", in case <b>
% begins with "+" or "-", so that the operator is considered as unary.
\def\intervsep{\mathord{;}\mkern3mu}
% Search for the opening delimiter.
\def\interv@I{%
\@ifnextchar[%
{\interv@II}% "[" found.
{\@ifnextchar]%
{\interv@II}% "]" found.
{\@ifnextchar\lr%
{\interv@III}% "\lr" found.
{\interv@IV}% "\big", "\Big", etc. found.
}}}
% Left delimiter found just after "\interv".
\def\interv@II{%
\def\first{\mathopen}%
\def\last{\mathclose}%
\interv@V}
% "\lr" found between "\interv" and the opening delimiter.
\def\interv@III#1{%
\def\first{\left}%
\def\last{\right}%
\interv@V}
% "\big", "\Big", etc. found between "\interv" and the opening delimiter.
\def\interv@IV#1{%
\def\first{\csname\expandafter\@gobble\string#1l\endcsname}%
\def\last{\csname\expandafter\@gobble\string#1r\endcsname}%
\interv@V}
% Process everything left of ",".
% Note: "\lr" and "\big", etc. have been absorbed by "\interv@III" and
% "\interv@IV", so #1 is always "[" or "]".
\def\interv@V#1#2,{\first#1#2\intervsep\mathopen{}\interv@VI}
% Search for the closing delimiter and read all tokens up to it.
\def\interv@VI{%
\@ifnextchar]%
{\interv@VII}% "]" found.
{\@ifnextchar[%
{\interv@VII}% "[" found.
{\@ifnextchar\bgroup%
{\interv@VIII}% list of tokens between braces found.
{\interv@IX}% single token found.
}}}
% Process closing delimiter. "\last" is "\mathclose" or "\right".
\def\interv@VII#1{\the\tok@list\last#1}
% Do not search for the closing delimiter within brace-delimited lists of
% tokens. Append them with enclosing braces to the main list and look for the
% next token.
\def\interv@VIII#1{\append@tok{{#1}}\tok@list\interv@VI}
% Append a single token to the main list and look for the main token.
\def\interv@IX#1{\append@tok#1\tok@list\interv@VI}
% Append a token to a list of tokens.
\newtoks\tok@list
\newtoks\next@tok
\def\append@tok#1#2{\next@tok={#1}%
\edef\do@append{\noexpand#2={\the#2\the\next@tok}}%
\do@append}
\makeatother
\begin{document}
% To check the effects of "\mathopen", "\mathclose", "\left", "\right" on
% binary and unary operators.
\thinmuskip=20mu
\medmuskip=40mu
% Works.
\verb|A \cap \interv]-a, +b[ \mathord\setminus B|:
\[A \cap \interv]-a, +b[ \mathord\setminus B\]
% Works.
\verb|A \cap \interv]-1{,}2, +3{,}4[ \mathord\setminus B|:
\[A \cap \interv]-1{,}2, +3{,}4[ \mathord\setminus B\]
% Works.
\verb|A \cap \interv\lr]-a, +\frac{b}{c}] \mathord\setminus B|:
\[A \cap \interv\lr]-a, +\frac{b}{c}] \mathord\setminus B\]
% Works.
\verb|A \cap \interv\Bigg[-a, +{b[c]}[ \mathord\setminus B|:
\[A \cap \interv\Bigg[-a, +{b[c]}[ \mathord\setminus B\]
\hrule\leavevmode
% Works.
\noindent\verb|A \cap \interv]-a, +b[ \mathord\setminus B|:
\section{$A \cap \interv]-a, +b[ \mathord\setminus B$}
% Complains that "\lr" is an undefined control sequence.
% "\left" and "\right" not used in the table of contents.
\verb|A \cap \interv\lr]-a, +\frac{b}{c}] \mathord\setminus B|:
\section{$\displaystyle A \cap \interv\lr]-a, +\frac{b}{c}] \mathord\setminus B$}
% Fails in the table of contents.
\verb|A \cap \interv\Bigg[-a, +{b[c]}[ \mathord\setminus B|:
\section{$A \cap \interv\Bigg[-a, +{b[c]}[ \mathord\setminus B$}
\tableofcontents
\end{document}
答案1
我不喜欢这种做事的方式:它很脆弱而且容易出错。
然而,对移动论证中的客体的保护很容易提供。
由于\interv
后面必然跟着一个标记(不是左括号),因此可以将其定义为
\def\interv#1{%
\ifx\protect\@typeset@protect
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\tok@list={}\interv@I#1}%
{\noexpand\interv\noexpand#1}%
}
所以当 LaTeX 没有排版时,它会看到\interv
其后的第一个标记并且不会扩展它们。
这或多或少就是我的做法。当然我不会使用反向括号:我同意 Don Knuth 的观点,这是一种变态(参见 TeXbook 练习 18.14)。;-)
我只是根据您的喜好调整了我的宏。请注意,这种输入代码的方式可以提供更大的灵活性。只需更改定义中的分隔符,您就可以在整本书中更改它们。
\documentclass{article}
\usepackage{amsmath,xparse,mleftright}
\ExplSyntaxOn
\NewDocumentCommand{\interval}{O{}>{\SplitArgument{1}{,}}m}
{
\group_begin:
\keys_set:nn { calcolo/interval } { o, #1 }
\bool_if:NTF { \l_calcolo_interval_auto_bool }
{\mleft\l_calcolo_interval_left_tl}
{\mathopen{\l_calcolo_interval_size_tl\l_calcolo_interval_left_tl}}
\calcolo_interval_set:nn #2
\bool_if:NTF { \l_calcolo_interval_auto_bool }
{\mright\l_calcolo_interval_right_tl}
{\mathclose{\l_calcolo_interval_size_tl\l_calcolo_interval_right_tl}}
\group_end:
}
\cs_new_protected:Nn \calcolo_interval_set:nn
{
#1 \l_calcolo_interval_sep_tl #2
}
\keys_define:nn { calcolo/interval }
{
size .code:n =
\tl_if_eq:nnTF { #1 } { * }
{ \bool_set_true:N \l_calcolo_interval_auto_bool }
{ \tl_set:Nx \l_calcolo_interval_size_tl { \exp_not:c {#1} } },
o .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { ] }
\tl_set:Nn \l_calcolo_interval_right_tl { [ },
oo .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { ] }
\tl_set:Nn \l_calcolo_interval_right_tl { [ },
c .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { [ }
\tl_set:Nn \l_calcolo_interval_right_tl { ] },
cc .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { [ }
\tl_set:Nn \l_calcolo_interval_right_tl { ] },
oc .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { ] }
\tl_set:Nn \l_calcolo_interval_right_tl { ] },
co .code:n =
\tl_set:Nn \l_calcolo_interval_left_tl { [ }
\tl_set:Nn \l_calcolo_interval_right_tl { [ },
o .value_forbidden:n = true,
oo .value_forbidden:n = true,
c .value_forbidden:n = true,
cc .value_forbidden:n = true,
oc .value_forbidden:n = true,
co .value_forbidden:n = true,
}
\tl_new:N \l_calcolo_interval_left_tl
\tl_new:N \l_calcolo_interval_right_tl
\tl_new:N \l_calcolo_interval_size_tl
\tl_new:N \l_calcolo_interval_sep_tl
\bool_new:N \l_calcolo_interval_auto_bool
\tl_set:Nn \l_calcolo_interval_sep_tl { \mathpunct{;} }
\ExplSyntaxOff
\begin{document}
$\interval{a,b}$
$\interval[o]{a,b}$ $\interval[c]{a,b}$
$\interval[oo]{a,b}$ $\interval[cc]{a,b}$
$\interval[oc]{a,b}$ $\interval[co]{a,b}$
\bigskip
\verb|A \cap \interval{-a, +b} \setminus B|:
\[A \cap \interval{-a, +b} \setminus B\]
% Works.
\verb|A \cap \interval{-1{,}2, +3{,}4} \setminus B|:
\[A \cap \interval{-1{,}2, +3{,}4} \setminus B\]
% Works.
\verb|A \cap \interval[oc,size=*]{-a, +\frac{b}{c}} \setminus B|:
\[A \cap \interval[oc,size=*]{-a, +\frac{b}{c}} \setminus B\]
% Works.
\verb|A \cap \interval[co,size=Bigg]{-a, +b[c]} \setminus B|:
\[A \cap \interval[co,size=Bigg]{-a, +b[c]} \setminus B\]
\bigskip
\hrule
\bigskip
% Works.
\noindent\verb|A \cap \interval{-a, +b} \setminus B|:
\section{$A \cap \interval{-a, +b} \setminus B$}
\verb|A \cap \interval[oc,size=*]{-a, +\frac{b}{c}} \setminus B|:
\section{$\displaystyle A \cap \interval[oc,size=*]{-a, +\frac{b}{c}} \setminus B$}
\verb|A \cap \interval[co,size=Bigg]{-a, +b[c]} \setminus B|:
\section{$A \cap \interval[co,size=Bigg]{-a, +b[c]} \setminus B$}
\tableofcontents
\end{document}