# Modify \funcdef macro to use pgfkeys instead of keyval

I attempted to modify the \funcdef macro from egreg's solution from A macro adding or removing parenthesis automatically to use pgfkeys, but am running into some difficulty (probably related to some expansion issues). The text highlighted in red details the failing conditions:

## Notes:

• The MWE seems long due to the \funcdef code, which is here in case one wishes to see the results with the other macro. The issues here are all related to the \FunctionMap macro.
• The main differences between the \FunctionMap macro here and the linked \funcdef (other than using pgfkeys instead of keyval) is that \FunctionMap:

• 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.

## Questions:

• What changes are needed to resolve the failing conditions highlighted in red.
• What case requires the use of the

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


## Code:

\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}
`
• /.estore in expands the argument so mathbf is destined to fail there. I think you just need to collect the tokens. – percusse Dec 10 '16 at 2:12
• @percusse: Well, that certainly was easy.. Thanks. You want to post that as an answer? – Peter Grill Dec 10 '16 at 7:09