![修改 `\funcdef` 宏以使用 `pgfkeys` 而不是 `keyval`](https://linux22.com/image/345792/%E4%BF%AE%E6%94%B9%20%60%5Cfuncdef%60%20%E5%AE%8F%E4%BB%A5%E4%BD%BF%E7%94%A8%20%60pgfkeys%60%20%E8%80%8C%E4%B8%8D%E6%98%AF%20%60keyval%60%20.png)
我尝试修改\funcdef
egreg 解决方案中的宏自动添加或删除括号的宏使用pgfkeys
,但遇到了一些困难(可能与一些扩展问题有关)。红色突出显示的文本详细说明了失败的情况:
笔记:
- 由于代码的原因,MWE 似乎很长
\funcdef
,这里是为了方便人们查看其他宏的结果。这里的问题都与宏有关\FunctionMap
。 \FunctionMap
此处的宏与链接的宏\funcdef
(除了使用pgfkeys
而不是)之间的主要区别keyval
在于\FunctionMap
:- 需要同时指定
domain=
和。codomain=
- 如果
variable=
提供则notation=
也必须提供。 array
仅当variable=
提供了时才使用。
- 需要同时指定
问题:
- 需要进行哪些更改来解决以红色突出显示的失败情况。
什么情况下需要使用
\ifx\Notation\@empty \expandafter\@gobble \else \expandafter\@firstofone \fi
参考:
- \@firstoftwo 和 \@secondoftwo 起什么作用?。
- 宏
funcdef
来自自动添加或删除括号的宏。 pgfkeys
解释如何使用如何创建带有键值的命令?。
代码:
\documentclass{article}
\usepackage{amsmath,keyval}
\usepackage{pgfkeys}
\usepackage{xstring}
\usepackage{xcolor}
\makeatletter%% ------ egreg's version from https://tex.stackexchange.com/a/149727/4301
\newcommand{\funcdef@key}[1]{%
\define@key{funcdef}{#1}{\@namedef{cet@#1}{##1}}%
\expandafter\let\csname cet@#1\endcsname\@empty
}
\funcdef@key{name}
\funcdef@key{domain}
\funcdef@key{codomain}
\funcdef@key{variable}
\funcdef@key{variables}
\funcdef@key{notation}
\funcdef@key{definition}
\newcommand{\funcdef@check}[1]{%
\expandafter\ifx\csname cet@#1\endcsname\@empty
\@latex@error{Missing `#1'}{Provide `#1'}%
\fi
}
\newcommand{\funcdef}[1]{%
\begingroup
\setkeys{funcdef}{#1}%
\ifx\cet@codomain\@empty\let\cet@codomain\cet@domain\fi
\funcdef@check{name}%
\funcdef@check{domain}%
\ifx\cet@variables\@empty
\funcdef@check{variable}%
\fi
\begin{array}{l@{}r@{}l@{}l}
\cet@name\colon{} &
\cet@domain &
{}\to \cet@codomain \\
&
\ifx\cet@variable\@empty
(\cet@variables)
\else
\cet@variable
\fi &
{}\mapsto
\ifx\cet@notation\@empty
\cet@name(
\ifx\cet@variable\@empty
\cet@variables
\else
\cet@variable
\fi
)
\else
\cet@notation
\fi
\ifx\cet@definition\@empty
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{& {}\mathrel{:}=\cet@definition}
\\
\end{array}
\endgroup
}
\makeatletter
%% -------------------------------- Modified pgfkeys version.
\pgfkeys{%
%% https://tex.stackexchange.com/a/34318/4301
/FunctionMap/.is family,% Define family directory
/FunctionMap,% Switch to this directory
default/.style={% Defaults
variable={},
%%notation={},%% No default so we get an error if variable is specified, but notation is not
},
name/.estore in = \Name,
domain/.estore in = \Domain,
codomain/.estore in = \Codomain,
variable/.estore in = \Variable,
notation/.estore in = \Notation,% Error if this is not specified, but variable is
}%
\newcommand{\FunctionMap}[1]{%
%% Requires both "domain=" and "codomain=" to be specified.
%% if "variable=" is provided then "notation=" must also be provided.
%% Only use an array if variable is provided
\begingroup%
\pgfkeys{/FunctionMap, default, #1}%
\IfStrEq{\Variable}{}{%
\Name\colon{}
\Domain
{}\mathrel{\to} \Codomain
}{%
\begin{array}{@{}l@{}r@{}l@{}l}
% https://tex.stackexchange.com/a/37791/4301
\Name\colon{}
& \Domain
& {}\mathrel{\to} \Codomain
\\
& \Variable
\ifx\Notation\@empty
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
& {}\mathrel{\mapsto} \Notation
\end{array}%
}%
\endgroup
}%
%% To switch to use \funcdef
%\let\FunctionMap\funcdef
\newcommand*{\Error}[1]{(\textcolor{red}{#1})}%
\begin{document}
\noindent
Simple function \Error{want to use `$\mathbf{R}$' here instead of `$R$'}:
\[
\FunctionMap{%
name=f,
domain=R, %\mathbf{R},% fails
codomain=R,% \mathbf{R},% fails
variable=x,
notation=f(x),
}
\]
Simple function with declaration:
\[
\FunctionMap{%
name=f,
domain=R,
codomain=R,
variable=x,
notation=x^2,
}
\]
Function with alternative writing \Error{Want to use `$\exp$' here instead of `$f$'}:
\[
\FunctionMap{%
name=f, %% \exp,% <-- fails
domain=R,
codomain=R,
variable=x,
notation=e^x
}
\]
Function with alternative writing and declaration:
\[
\FunctionMap{%
name=g,
variable=x,
domain=R,
codomain=R,
notation={e^x:=\lim\limits_{n\to\infty}\left(1+\frac xn\right)^n}
}
\]
Function with different domain and codomain
\Error{Want to use `$\operatorname{sqrt}$' and `$\sqrt{n}$' here instead of `$sqrt$'}:
\[
\FunctionMap{%
name=sqrt, %%\operatorname{sqrt},% <-- fails
domain=N, %\mathbf{N},% <-- fails
codomain=R,%\mathbf{R},% <-- fails
variable=n,
notation=sqrt{n}, %% \sqrt{n},% <-- fails
}
\]
%Function with different domain and codomain, alternative writing
%and declaration:
%\[
%\FunctionMap{%
% name=\operatorname{sqrt},
% domain=\mathbf{N},
% codomain=\mathbf{R},
% variable=n,
% notation=\sqrt{n},
% definition=\exp\bigl(\frac{1}{2}\ln n\bigr)
%}
%\]
Function of two variables:
\[
\FunctionMap{%
name=f,
domain=A\times B,
codomain=C,
variable={(a,b)},
notation=f(x),
}
\]
Function of with just domain and codomain:
\[
\FunctionMap{%
name=f,
domain=X,
codomain=Y,
}
\]
\end{document}