我有一个命令\cont
主要以 的形式使用\cont{X, Y}
,并使用 进行定义\SplitArgument
,如下面的源代码所示。我如何重新定义(即扩展 的定义)\cont
以允许 4 个参数而不是 2 个参数,这些参数成对分组,如 outout 等式 (2) 所示?
请注意,当只有 2 个参数时,我想继续使用逗号作为分隔符,例如\cont{X, Y}
。但是当有 4 个参数时,我想将(主)分隔符更改为分号,同时保留逗号作为辅助分隔符,例如\cont{X, x; Y, y}
。
\documentclass[fleqn]{memoir}
\usepackage{xparse}
\NewDocumentCommand{\cont}{ >{\SplitArgument{1}{,}} m }{\printcont#1}
\NewDocumentCommand{\printcont}{mm}{{\mathcal{C}}({#1}\IfValueT{#2}{, {#2}})}
\begin{document}
\noindent Equation~(\ref{one}) shows use of \verb!\cont! with 2 arguments, as in \verb!\cont{X, Y}!, with comma as separator:
\begin{equation}\label{one}
\cont{X, Y}
\end{equation}
\noindent How can we \emph{extend} the definition of \verb!\cont! so that\dots\\[6pt]
\mbox{}\qquad\verb!\cont{X, x; Y, y}! \\[6pt]
---with commas and a single semicolon as separators----gives the same result as equation~(\ref{two}), below?
\begin{equation}\label{two}
\mathcal{C}[(X, x), (Y, y)]
\end{equation}
\end{document}
答案1
我会立即发出\mathcal{C}
,然后将控制权传递给另一个检查分号并采取适当操作的命令。
\documentclass[fleqn]{memoir}
\usepackage{amsmath}
\NewDocumentCommand{\cont}{>{\SplitArgument{1}{;}}m}{%
\mathcal{C}%
\printcont#1%
}
\NewDocumentCommand{\printcont}{mm}{%
\IfNoValueTF{#2}{%
\conttwo{#1}%
}{%
[\conttwo{#1},\conttwo{#2}]%
}%
}
\NewDocumentCommand{\conttwo}{>{\SplitArgument{1}{,}}m}{%
\printconttwo#1%
}
\NewDocumentCommand{\printconttwo}{mm}{%
(#1\IfValueT{#2}{,#2})%
}
\begin{document}
\begin{gather*}
\cont{X} \\
\cont{X, Y} \\
\cont{X;Y} \\
\cont{X,x;Y} \\
\cont{X, x;Y, y}
\end{gather*}
\end{document}
如果您想在括号中添加\bigl
和,则传递整个参数。\bigr
\cont*
\documentclass[fleqn]{memoir}
\usepackage{amsmath}
\NewDocumentCommand{\cont}{s>{\SplitArgument{1}{;}}m}{%
\mathcal{C}%
\printcont{#1}#2%
}
\NewDocumentCommand{\printcont}{mmm}{%
\IfNoValueTF{#3}{%
\conttwo{#2}%
}{%
\IfBooleanT{#1}{\bigl}[%
\conttwo{#2},\conttwo{#3}
\IfBooleanT{#1}{\bigr}]%
}%
}
\NewDocumentCommand{\conttwo}{>{\SplitArgument{1}{,}}m}{%
\printconttwo#1%
}
\NewDocumentCommand{\printconttwo}{mm}{%
({#1}\IfValueT{#2}{, {#2}})
}
\begin{document}
\begin{gather*}
\cont{X} \\
\cont{X, Y} \\
\cont{X;Y} \\
\cont{X,x;Y} \\
\cont{X, x;Y, y} \\
\cont*{X,x;Y} \\
\cont*{X, x;Y, y}
\end{gather*}
\end{document}
答案2
\cont
仅使用 TeX 原语定义的宏:
\def\cont#1{\contA#1;\end}
\def\contA#1;#2\end{\ifx;#2;{\cal C}(#1)\else\contB#1;#2\fi}
\def\contB#1;#2;{{\cal C}\bigl[(#1),(#2)\bigr]}
%% test:
$$\displaylines{
\cont{X} \cr
\cont{X, Y} \cr
\cont{X;Y} \cr
\cont{X,x;Y} \cr
\cont{X, x;Y, y}
}$$
\bye
答案3
以下方法使用etoolbox
的列表处理功能来设置提供的参数\cont
,用分隔参数(列表);
,然后有条件地设置列表:单个项目的设置与项目列表不同。
\documentclass{article}
\usepackage{etoolbox}
\DeclareListParser{\contlist}{;}% Processes a list using ; as separator
\newcounter{contcount}
\newcommand{\cont}[1]{%
\setcounter{contcount}{0}% Reset counter
\renewcommand*{\do}[1]{\stepcounter{contcount}}% Count items in list
\contlist{#1}% Count elements in list
\ifnum\value{contcount}<2
\mathcal{C}(#1)% Singular element
\else % \value{contcount}>1
\mathcal{C}[
% https://tex.stackexchange.com/a/89187/5764
\newcommand{\contitemsep}{\renewcommand{\contitemsep}{,}}% Delayed definition of \contitemsep
\renewcommand*{\do}[1]{\contitemsep(##1)}% How each item in list should be printed
\contlist{#1}% Print entire list
]
\fi
}
\begin{document}
\noindent Equation~(\ref{one}) shows use of \verb!\cont! with 2 arguments, as in \verb!\cont{X, Y}!, with comma as separator:
\begin{equation}\label{one}
\cont{X, Y}
\end{equation}
\noindent How can we \emph{extend} the definition of \verb!\cont! so that\dots
\qquad\verb!\cont{X, x; Y, y}!
---with commas and a single semicolon as separators----gives the same result as equation~(\ref{two}), below?
\begin{equation}\label{two}
\cont{X, x; Y, y}
\end{equation}
\end{document}
答案4
此变体不愿意添加括号,并且此变体与\cont{X,Y}
相同, \cont{X;Y}
并且\cont*{X,Y}
与 相同 ,即,仅当 的非星号参数\cont*{X;Y}
中同时出现逗号和分号时,才会得到方括号。\cont
\documentclass[fleqn]{memoir}
\usepackage{amsmath}
\NewDocumentCommand{\cont}{s>{\SplitArgument{1}{;}}m}{%
% #1 - \BooleanTrue/\BooleanFalse - flag / control-word-token
% denoting the presence/non-presence of star.
% #2 - user-provided argument, split in two brace-nested arguments, one holding
% "things before first semicolon", the other holding "things behind first semicolon".
\conttwo#2{#1}%
}
\NewDocumentCommand{\conttwo}{>{\SplitArgument{1}{,}}mm}{%
% #1 - things before first semicolon, split in two brace-nested arguments at first comma.
% #2 - things behind first semicolon
% You need to check if #2 is the NoValue-marker as
% xparse-argument-processors like \SplitArgument do not work on
% the NoValue-Marker
\IfNoValueTF{#2}{\printcont{#2}}{\contthree}{#2}#1%
}
\NewDocumentCommand{\contthree}{>{\SplitArgument{1}{,}}m}{%
% #1 - things behind first semicolon, split in two brace-nested arguments at first comma.
\printcont#1%
}
\NewDocumentCommand\printcont{mmmmm}{%
% #1 - first component of things behind first semicolon after splitting these things at first comma.
% #2 - second component of things behind first semicolon after splitting these things at first comma.
% #3 - first component of things before first semicolon after splitting these things at first comma.
% #4 - second component of things before first semicolon after splitting these things at first comma.
% #5 - \BooleanTrue/\BooleanFalse - flag denoting presence of star.
\mathcal{C}%
\IfNoValueTF{#1}{%
(#3\IfNoValueF{#4}{,#4})% <-only commas
}{%
\IfNoValueTF{#4}{%
\IfNoValueTF{#2}{(#3,#1)}% <-only semicolons
{\IfBooleanT{#5}{\bigl}[#3,(#1,#2)\IfBooleanT{#5}{\bigr}]}%
}%
{\IfBooleanT{#5}{\bigl}[(#3,#4),\IfNoValueTF{#2}{#1}{(#1,#2)}\IfBooleanT{#5}{\bigr}]}%
}%
}%
\begin{document}
\Huge
\begin{tabular}{|l|l|}
\hline
\(\cont{X}\)&\(\cont*{X}\) \\
\hline
\(\cont{X, Y}\)&\(\cont*{X, Y}\) \\
\hline
\(\cont{X;Y}\)&\(\cont*{X;Y}\) \\
\hline
\(\cont{X,x;Y}\)&\(\cont*{X,x;Y}\) \\
\hline
\(\cont{X;Y, y}\)&\(\cont*{X;Y, y}\) \\
\hline
\(\cont{X, x;Y, y}\)&\(\cont*{X, x;Y, y}\)\\
\hline
\end{tabular}
\end{document}