# Problem with nesting macros

I have written a macro to denote either the Fourier transformation (curly F by itself) or the Fourier transform of a function (curly F followed by a function and enclosed in \left( and \right) ). It does so by testing if the argument is equal to void or not:

\newcommand*{\fourier}[1]{\ensuremath{\mathscr{F}\ifthenelse{\equal{#1}{}}{}{\!\left({#1}\right)}}}%


Therefore

\fourier{}


or

\fourier{f(\omega t)}


give the expected results.

I wanted to apply \fourier twice to a function and therefore wrote

\fourier{\fourier{f}}(x)


However, I'm getting a ! Missing \endcsname inserted. error. How should I modify my macro so that it allows nesting? I'm guessing it's because of the \ifthenelse construct?

Similar to Skillmon's original answer, but pretending to be mathtools and sticking to the mandatory argument. The starred version uses \left/\right, the unstarred version has an optional parameter for \big/\Big/...

Taking the approach to \left and \right from Mateus Araújo's answer to Spacing around \left and \right with help from Philipp Stephani (thanks to Ruixi Zhang for the suggestion in the comments)

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{amsmath}
\usepackage{mathrsfs}
\usepackage{ifthen}

\makeatletter
\DeclareRobustCommand{\fourier}{%
\mathscr{F}%
\@ifstar
\fourier@paren@star
\fourier@paren@expl}
\newcommand{\fourier@paren@star}[1]{%
\if\relax\detokenize{#1}\relax
\else
\mathopen{}\mathclose{\left(#1\right)}%
\fi}
\newcommand{\fourier@paren@expl}[2][]{%
\if\relax\detokenize{#2}\relax
\else
\mathopen{#1(}#2\mathclose{#1)}%
\fi}
\makeatother

\begin{document}
$\fourier{}$
$\fourier{f(\omega t)}$
$\fourier{\fourier{f}}(x)$
$\fourier*{\fourier*{\frac{f^2}{2\pi}}}(x)$
\end{document}


• That space \! before \left and \right though. Why not use the classic solution by Philipp Stephani: \mathopen{}\mathclose{\left( #1 \right)}. For the \fourier[\big]{...} variants, I was wondering if there is a possible direct use of \bigl and \bigr. ;-) – Ruixi Zhang Sep 5 '18 at 15:56
• @RuixiZhang Thanks for the hint. I had copied the \left \right bit from the OP. I'll see if I can find something that works for \big->\bigl/\bigr, though I'm not sure if that is necessary when we already use \mathopen and \mathclose. – moewe Sep 5 '18 at 16:06
• @RuixiZhang Given that \bigl is just \def\bigl{\mathopen\big} I don't think the conversion from \big to \bigl is really necessary here. If anyone is interested I came up with \newcommand{\frde@size@getlr}[3]{\csname\expandafter\@gobble\string#1#2\endcsname#3} which you can use as \frde@size@getlr{\big}{l}{(} to get \bigl(. – moewe Sep 5 '18 at 19:26
• You are right. Unlike the “simple wrapper” from mathtools which does \@nameuse {\MH_cs_to_str:N ##1 l} #2 and \@nameuse {\MH_cs_to_str:N ##1 r} #3, going this extra mile to get \bigl( just seems convoluted. – Ruixi Zhang Sep 5 '18 at 19:47
• @FrédéricDelacroix Many expert users prefer the explicit size commands over the automatic sizing with \left/\right because the automatic commands may pick out sizes that are unnecessarily large or too small in certain situations (there is even a quote from the TeXbook that acknowledges that and it is reproduced in an answer here, but I can't find that right now). – moewe Sep 6 '18 at 8:13

I'd use the following:

1. don't use \ensuremath it tends to obfuscate source code
2. don't use \ifthenelse to check for an empty argument, but \if\relax\detokenize{#1}\relax (expandable, plus personal preferences)
3. use an optional argument for an optional argument

I've made a mistake therefore the former code grabbed the arguments wrong. The following uses xparse to grab the arguments in a more robust way. It therefore doesn't use the \if\relax\detokenize{#1}\relax test but xparse's \IfValueT.

Results:

\documentclass[]{article}

\usepackage{mathrsfs}
\usepackage{xparse}

\NewDocumentCommand \fourier { o }
{%
\mathscr{F}\IfValueT{#1}{\!\left(#1\right)}%
}%

\begin{document}
$\fourier[\fourier[f]](x)$
\end{document}