修改 `\funcdef` 宏以使用 `pgfkeys` 而不是 `keyval`

修改 `\funcdef` 宏以使用 `pgfkeys` 而不是 `keyval`

我尝试修改\funcdefegreg 解决方案中的宏自动添加或删除括号的宏使用pgfkeys,但遇到了一些困难(可能与一些扩展问题有关)。红色突出显示的文本详细说明了失败的情况:

在此处输入图片描述

笔记:

  • 由于代码的原因,MWE 似乎很长\funcdef,这里是为了方便人们查看其他宏的结果。这里的问题都与宏有关\FunctionMap
  • \FunctionMap此处的宏与链接的宏\funcdef(除了使用pgfkeys而不是)之间的主要区别keyval在于\FunctionMap

    • 需要同时指定domain=和。codomain=
    • 如果variable=提供则notation=也必须提供。
    • array仅当variable=提供了时才使用。

问题:

  • 需要进行哪些更改来解决以红色突出显示的失败情况。
  • 什么情况下需要使用

    \ifx\Notation\@empty
        \expandafter\@gobble
    \else
        \expandafter\@firstofone
    \fi
    

参考:

代码:

\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}

相关内容