目的
我想要一个命令来根据需要写入“其中#1
是任意常数”、“其中#1
是任意常数”、“其中#1
是任意函数#2
”或“其中#1
是任意函数”。#2
背景
通常,让单复数检测依赖于 中逗号的存在与否就足够了#1
。为此,以下函数可以正常工作。
\documentclass{article}
\usepackage{xstring,xargs,xifthen,amsmath}
\newcommandx{\arbitrary}[3][1=\text{ where }, 3=]{%
#1#2%
\IfSubStr{#2}{,}{\text{ are}}{\text{ is an}}%
\text{ arbitrary}%
\ifthenelse{\equal{#3}{}}{\text{ constant}}{\text{ function}}%
\IfSubStr{#2}{,}{\text{s}}{}%
\ifthenelse{\equal{#3}{}}{}{\text{ of }#3}
}
\begin{document}
\begin{align*}
& \arbitrary{a} \\ % where a is an arbitrary constant
& \arbitrary{a,b} \\ % where a,b are arbitrary constants
& \arbitrary{f}[x] \\ % where f is an arbitrary function of x
& \arbitrary{f,g}[x] % where f,g are arbitrary functions of x
\end{align*}
\end{document}
但有时我想将一个单数参数复数化,例如
2a_n+1, \text{ where $a_n$ are arbitrary constants, } n \in \{1,2,\dots\}
为此,我尝试使用可选参数实现备份检测机制。这涉及定义两个条件,函数将根据这两个条件将其视为#1
复数:如果#1
包含逗号,或者如果#4=p
为复数。
\documentclass{article}
\usepackage{xstring,xargs,xifthen}
\newcommandx{\arbitrary}[4][1=\text{ where }, 3=, 4=]{%
#1#2%
\ifthenelse{%
1=\IfSubStr{#2}{,}{1}{0}\OR%
\equal{#4}{p}%
}{\text{ are}}{\text{ is}}%
\text{ arbitrary}%
\ifthenelse{\equal{#3}{}}{\text{ constant}}{\text{ function}}%
\ifthenelse{%
1=\IfSubStr{#2}{,}{1}{0}\OR%
\equal{#4}{p}%
}{\text{s}}{}%
\ifthenelse{\equal{#3}{}}{}{\text{ of }#3}
}
\begin{document}
I wish this function worked.
\end{document}
问题
LaTeX 似乎不喜欢这种语法\ifthenelse{1=\IfSubStr{ab}{a}{1}{0}}{1}{0}
。
\documentclass{article}
\usepackage{xstring,xifthen}
\begin{document}
\IfSubStr{ab}{a}{1}{0} % returns 1
\ifthenelse{1=1}{1}{0} % returns 1
\ifthenelse{1=\IfSubStr{ab}{a}{1}{0}}{1}{0} % returns error
\end{document}
答案1
扩展版本还处理多变量函数。* 版本强制使用复数。
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\arbitrary}{smo}
{% #1 = boolean for forcing plural
% #2 = mandatory argument
% #3 = optional argument for the variable
\IfBooleanTF{#1}
{ \bool_set_true:N \l_mjc_arbitrary_plural_bool }
{ \bool_set_false:N \l_mjc_arbitrary_plural_bool }
\IfNoValueTF{#3}
{ \mjc_arbitrary_constant:n { #2 } }
{ \mjc_arbitrary_function:nn { #2 } { #3 } }
}
\bool_new:N \l_mjc_arbitrary_plural_bool
\seq_new:N \l__mjc_arbitrary_variables_seq
\seq_new:N \l__mjc_arbitrary_variables_out_seq
\cs_new_protected:Nn \mjc_arbitrary_constant:n
{
\bool_lazy_or:nnTF
{ \l_mjc_arbitrary_plural_bool }
{ \int_compare_p:n { \clist_count:n { #1 } > 1 } }
{ \mjc_arbitrary_phrases:nnnn { #1 } { are } { constants } { } }
{ \mjc_arbitrary_phrases:nnnn { #1 } { is~an } { constant } { } }
}
\cs_new_protected:Nn \mjc_arbitrary_function:nn
{
\bool_lazy_or:nnTF
{ \l_mjc_arbitrary_plural_bool }
{ \int_compare_p:n { \clist_count:n { #1 } > 1 } }
{ \mjc_arbitrary_phrases:nnnn { #1 } { are } { functions } { #2 } }
{ \mjc_arbitrary_phrases:nnnn { #1 } { is~an } { functions } { #2 } }
}
\cs_new_protected:Nn \mjc_arbitrary_phrases:nnnn
{% #1 = object, #2 = verb, #3 = type, #4 = optional variable
\mode_if_math:TF
{ \text { \__mjc_arbitrary_phrases:nnnn { #1 } { #2 } { #3 } { #4 } } }
{ \__mjc_arbitrary_phrases:nnnn { #1 } { #2 } { #3 } { #4 } }
}
\cs_new_protected:Nn \__mjc_arbitrary_phrases:nnnn
{
where~$#1$~#2~arbitrary~#3
\tl_if_blank:nF { #4 }
{
\seq_set_from_clist:Nn \l__mjc_arbitrary_variables_seq { #4 }
\c_space_tl of~the~variable
\int_compare:nT { \seq_count:N \l__mjc_arbitrary_variables_seq > 1 } { s }
\nobreakspace
\__mjc_arbitrary_variables:
}
}
\cs_new_protected:Nn \__mjc_arbitrary_variables:
{
\seq_set_map:NNn \l__mjc_arbitrary_variables_out_seq \l__mjc_arbitrary_variables_seq { $##1$ }
\seq_use:Nnnn \l__mjc_arbitrary_variables_out_seq { ~and~ } { ,~ } { ,~and\nobreakspace }
}
\ExplSyntaxOff
\begin{document}
\begin{align*}
& \arbitrary{a} \\ % where a is an arbitrary constant
& \arbitrary*{a_n} \\ % where a_n are arbitrary constants
& \arbitrary{a,b} \\ % where a,b are arbitrary constants
& \arbitrary{f}[x] \\ % where f is an arbitrary function of x
& \arbitrary{f,g}[x] \\% where f,g are arbitrary functions of x
& \arbitrary{f}[x,y] \\ % where f is an arbitrary function of x and y
& \arbitrary{f,g}[x,y] \\% where f,g are arbitrary functions of x, y, and z
& \arbitrary*{f_n}[x] \\ % where f is an arbitrary function of x
& \arbitrary*{f_n}[x,y] % where f is an arbitrary function of x and y
\end{align*}
\arbitrary{a},
\arbitrary*{a_n},
\arbitrary{a,b},
\arbitrary{f}[x],
\arbitrary{f,g}[x],
\arbitrary*{f_n}[x].
\end{document}
我仅当在数学模式下找到该命令时才使用\text
;在文本模式下,您不希望使东西跨行牢不可破。
稍微复杂一点的是使用~
您想要的空间,但它只需要一点练习。
答案2
我用etoolbox
,
以第一个参数中的 为条件(通过\patchcmd{<cmd>}{<search>}{<replace>}{<success>}{<failure>}
)。这提供了第一个条件分支。然后我使用 来以结束可选参数的存在为条件xparse
的\IfValueTF{<arg>}{<true>}{<false>}
。
\documentclass{article}
% \usepackage{xparse}% Only if you have LaTeX < 2020-10
\usepackage{etoolbox,amsmath}
\NewDocumentCommand{\arbitrary}{m o}{
\def\firstarg{#1}% Store mandatory argument
\text{ where }
\firstarg
\IfValueTF{#2}
{\patchcmd{\firstarg}{,}{,}
{\text{ are arbitrary functions of } #2}% Contains a comma , => plural
{\text{ is an arbitrary function of } #2}}% Does not contain a comma , => singular
{\patchcmd{\firstarg}{,}{,}
{\text{ are arbitrary constants}}% Contains a comma , => plural
{\text{ is an arbitrary constant}}}% Does not contain a comma , => singular
}
\begin{document}
\begin{align*}
& \arbitrary{a} \\ % where a is an arbitrary constant
& \arbitrary{a,b} \\ % where a,b are arbitrary constants
& \arbitrary{f}[x] \\ % where f is an arbitrary function of x
& \arbitrary{f,g}[x] % where f,g are arbitrary functions of x
\end{align*}
\end{document}
如果你想力量为单数项输出复数,您可以\arbitrary
采用星号 - \arbitrary*
。这是您使用该条件的方式:
\documentclass{article}
% \usepackage{xparse}% Only if you have LaTeX < 2020-10
\usepackage{etoolbox,amsmath}
\NewDocumentCommand{\arbitrary}{s m o}{
\def\firstarg{#2}% Store mandatory argument
\text{ where }
\firstarg
\IfBooleanTF{#1}
{\text{ are arbitrary constants}}% Starred version => plural
{
\IfValueTF{#3}
{\patchcmd{\firstarg}{,}{,}
{\text{ are arbitrary functions of } #3}% Contains a comma , => plural
{\text{ is an arbitrary function of } #3}}% Does not contain a comma , => singular
{\patchcmd{\firstarg}{,}{,}
{\text{ are arbitrary constants}}% Contains a comma , => plural
{\text{ is an arbitrary constant}}}% Does not contain a comma , => singular
}
}
\begin{document}
\begin{align*}
& \arbitrary{a} \\ % where a is an arbitrary constant
& \arbitrary*{a_n} \\ % where a_n are arbitrary constants
& \arbitrary{a,b} \\ % where a,b are arbitrary constants
& \arbitrary{f}[x] \\ % where f is an arbitrary function of x
& \arbitrary{f,g}[x] % where f,g are arbitrary functions of x
\end{align*}
\end{document}