我使用一个小助手定义了一堆函数(或者运算符,如果你愿意的话)\parens
,它可以根据需要添加括号:
\newcommand{\parens}[1]{
\ifthenelse{\equal{#1}{}}{}{(#1)}
}
\newcommand{\fv}[1]{\text{fv}\parens{#1}}
这样,我不仅可以写\fv{e}
“fv(e)”,还可以写\fv{} \colon Expr \to Var
“fv : Expr → Var”。
从理论上讲,如果参数是一个符号,即,我通常会省略括号,fv e
但仍然如此fv (e₁ e₂)
。
如果参数计算结果为单个符号,我该如何增强我的\parens
宏以避免添加括号?
它不必是完美的,并且可能会因添加不必要的括号而犯错误。
以下是可供尝试的 MWE:
\documentclass{article}
\usepackage{amsmath}
\usepackage{ifthen}
\newcommand{\parens}[1]{
\ifthenelse{\equal{#1}{}}{}{(#1)}
}
\newcommand{\fv}[1]{\text{fv}\parens{#1}}
\begin{document}
Has no parentheses: $\fv{}$.
Should have no parentheses: $\fv{e}$, $\fv{\alpha}$.
Should have parentheses: $\fv{e_1 + e_2}$, $\fv{e_1+e_2}$, $\fv{e_1, e_2, \ldots}$.
These also could have no parentheses: $\fv{e_1}$
(but that is probably too much to ask)
\end{document}
答案1
您可以使用正则表达式来执行此操作,在检查参数是否为空后:如果参数仅匹配一个标记或一个后跟一个下标的标记_
,则不使用括号。
\documentclass{article}
\usepackage{amsmath}
\DeclareMathOperator{\fvop}{fv}
\ExplSyntaxOn
\NewDocumentCommand{\fv}{m}
{
\fvop
\tl_if_blank:nF { #1 }
{
\regex_match:nnTF { \A . ( \_. | \_\{.*?\} )? \Z } { #1 }
{
#1
}
{
(#1)
}
}
}
\ExplSyntaxOff
\begin{document}
Has no parentheses: $\fv{}$.
Has no parentheses: $\fv{e_1}$.
Should have no parentheses: $\fv{e}$, $\fv{\alpha}$, $\fv{\alpha_{12}}$.
Should have parentheses: $\fv{e+f}$, $\fv{\alpha+\beta}$.
Should have parentheses: $\fv{e+f}$, $\fv{\alpha+\beta}$.
Should have parentheses: $\fv{e_1 + e_2}$, $\fv{e_1+e_2}$, $\fv{e_1, e_2, \ldots}$.
\end{document}
可以使用标准方法获得\fv*{...}
强制自动扩展括号的扩展版本,而\fv[\big]{...}
如果参数不是单个变量(您也可以使用\Big
、\bigg
或),则使用更大的版本。\Bigg
mathtools
\documentclass{article}
\usepackage{amsmath,mathtools}
\DeclareMathOperator{\fvop}{fv}
\DeclarePairedDelimiter{\paren}{(}{)}
\ExplSyntaxOn
\NewDocumentCommand{\fv}{som}
{
\fvop
\IfBlankF{#3}
{
\IfBooleanTF{#1}
{
\paren*{#3}
}
{
\tl_if_blank:nF { #3 }
{
\regex_match:nnTF { \A . ( \_. | \_\{.*?\} )? \Z } { #3 }
{
#3
}
}
{
\IfNoValueTF{#2}{\paren{#3}}{\paren[#2]{#3}}
}
}
}
}
\ExplSyntaxOff
\begin{document}
Has no parentheses: $\fv{}$.
Has no parentheses: $\fv{e_1}$.
Should have no parentheses: $\fv{e}$, $\fv{\alpha}$, $\fv{\alpha_{12}}$.
Should have parentheses: $\fv{e+f}$, $\fv{\alpha+\beta}$.
Should have parentheses: $\fv{e+f}$, $\fv{\alpha+\beta}$.
Should have parentheses: $\fv{e_1 + e_2}$, $\fv{e_1+e_2}$, $\fv{e_1, e_2, \ldots}$.
Should have parentheses: $\fv*{\frac{e}{2}}$; compare with $\fv{\frac{e}{2}}$.
\[
\fv*{\frac{e}{2}}\quad\fv[\big]{\frac{e}{2}}\quad \fv*{e}\quad \fv[\big]{e}
\]
\end{document}
答案2
“单一符号”的概念有些模糊:我可以提出一个精确的测试来判断论证是否是一个单一的令牌。
\documentclass{article}
\makeatletter
\newcommand*\IsOnlyOneToken[1]{%
TT\fi
\@IsOnlyOneToken#1\@@@
}
\@ifdefinable\@IsOnlyOneToken{\def\@IsOnlyOneToken#1#2\@@@{%
\ifx\@empty#2\@empty
}}
\makeatother
\newcommand*{\clientCommand}[1]{%
\mathrm{fv}%
\if\IsOnlyOneToken{#1}%
\,#1%
\else
\left(#1\right)%
\fi
}
\begin{document}
Single token:
$\clientCommand{x}$,
$\clientCommand{\alpha}$.
Multiple tokens:
$\clientCommand{x+1}$,
$\clientCommand{x_{1}}$.
But an override is available:
$\clientCommand{{x_{1}}}$.
\end{document}
以下是输出(然而,这并不重要:您需要自己尝试一下……):
如您所见,如果您用一对额外的括号将参数括起来,测试会将参数视为单个标记。我认为这是一项功能,而不是错误。
编辑
\IsOnlyOneToken
如果使用空参数调用,即包含以下参数,则上述代码将失败:零标记。下面是解决方法:
\documentclass{article}
\makeatletter
\newcommand*\IsExactlyOneToken[1]{%
TT\fi
\ifx\@empty#1\@empty
\expandafter\@EmptyCase
\else
\expandafter\@IsOnlyOneToken
\fi
#1\@@@
}
\@ifdefinable\@IsOnlyOneToken{\def\@IsOnlyOneToken#1#2\@@@{%
\ifx\@empty#2\@empty
}}
\@ifdefinable\@EmptyCase{\def\@EmptyCase#1\@@@{% #1 for robustness
\iffalse % since 0 != 1
}}
\makeatother
\newcommand*{\clientCommand}[1]{%
\mathrm{fv}%
\if\IsExactlyOneToken{#1}%
\,#1%
\else
\nonscript\!\left(#1\right)%
\fi
}
\begin{document}
Single token:
$\clientCommand{x}$,
$\clientCommand{\alpha}$.
Multiple tokens:
$\clientCommand{x+1}$,
$\clientCommand{x_{1}}$.
But an override is available:
$\clientCommand{{x_{1}}}$.
The bug has been corrected:
$\clientCommand{}$\ldots
\makeatletter
\ldots also for ``pathological'' cases:
$\clientCommand\@empty$, $\clientCommand{\@empty}$.
Override: $\clientCommand{{\@empty}}$.
\makeatother
\end{document}
输出:
答案3
宏\IfSubStr
可以xstring
查找字符串之间的空白字符(也就是空格)。但是,这并不是万无一失的。
\documentclass{article}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage{mathtools}
\newcommand{\parens}[1]{
\ifthenelse{\equal{#1}{}}{}{(#1)}
}
\newcommand{\myarg}{e_{1} e_{2}}
\newcommand{\myotherarg}{e_{1} }
\newcommand{\fv}[1]{\text{fv}%
\IfSubStr{#1}{ }{%
\parens{#1}
}{\,#1}
}
\begin{document}
$\fv{v}$
$\fv{e_{1} e_{2}}$
$\fv{\myarg}$
$\fv{\myotherarg}$
\end{document}
答案4
仅基于 TeX 原语和简单的纯 TeX 宏的解决方案:
\newif\ifsingle
\def\issingle #1#2\iftrue{%
\singlefalse
\ifx&\singletrue
\else \issingleA #2\iftrue \issingleB #2\iftrue \singletrue
\fi \fi \fi
\ifsingle
}
\def\issingleA #1#2\iftrue {\ifx #1_}
\def\issingleB _#1#2\iftrue {\ifx&}
\def\fv#1{\mathop{\rm fv}%
\ifx&% empty parameter, do nothig
\else \issingle #1\iftrue {#1}\else ({#1})\fi
\fi
}
Has no parentheses: $\fv{}$.
Has no parentheses: $\fv{e_1}$.
Should have no parentheses: $\fv{e}$, $\fv{\alpha}$, $\fv{\alpha_{12}}$.
Should have parentheses: $\fv{e+f}$, $\fv{\alpha+\beta}$.
Should have parentheses: $\fv{e_1 + e_2}$, $\fv{e_1+e_2}$, $\fv{e_1, e_2, \ldots}$.
Should have parentheses: $\fv{e\over2}$.