12

Based on this solution related to defining a macro I came up with this macro to help me define a macro that I can use either in or outside of math mode.

The example as is functions as I want. However, this solution requires me to NOT put $$ around the second parameter to to the \DefineNamedFunction macro. I would like to be able to include the $$, or not include it.

One solution is to modify \DefineNamedFunction to strip out the $$ if it is included in the macro call using the xstring pacakge, but this to me feels like a hack, and am thinking that there is probably a cleaner TeX way to do this.

So to summarize: How do I change \DefineNamedFunction such that I can use both the commented and uncommented calls to this macro, and still be able to use the definition inside and outside of math mode?

\documentclass{article}

\usepackage{amsmath}
\usepackage{xcolor}

\newcommand{\DefineNamedFunction}[2]{% {FunctionName}{FunctionExpression}
    \expandafter\providecommand\expandafter{\csname#1\endcsname}{\textcolor{red}{\ensuremath{#2}}}%
}

\begin{document}

\DefineNamedFunction{FunctionF}{y = 2 \sin x}
%\DefineNamedFunction{FunctionF}{$y = 2 \sin x$}

I can use FunctionF inside math mode as $\FunctionF$,
but can also use this outside of math mode as \FunctionF.

\end{document}
Peter Grill
  • 223,288

2 Answers2

7

Probably

\ensuremath{\textcolor{red}{#2}}

is what you need, since \textcolor can be used in text and in math. The complete definition is

\newcommand{\DefineNamedFunction}[2]{% {FunctionName}{FunctionExpression}
    \expandafter\providecommand\csname#1\endcsname
      {\ensuremath{\textcolor{red}{#2}}}%
}
...
\DefineNamedFunction{FunctionF}{y=2\sin x}
$\FunctionF$ and \FunctionF

Sample

I've also deleted the braces that require another \expandafter, but that's not the problem.

Of course, you can't call

\DefinedNamedFunction{FunctionFF}{$y=x$}

and I wouldn't know why you'd want it. But in any case there's a simple solution

\newcommand{\DefineNamedFunction}[2]{%
  \expandafter\providecommand\csname#1\endcsname
    {\ensuremath{\begingroup\color{red}\DNFnorm#2\endgroup}}}
\makeatletter
\def\DNFnorm{\@ifnextchar$\DNFnormi{}}
\def\DNFnormi$#1${#1}
\makeatother

The input is "normalized" by removing the $ tokens before and after, if present.

With \begingroup\color{red}...\endgroup the spaces in the subformula participate to the stretching and shrinking of the spaces in the line.

egreg
  • 1,121,712
  • That does not seem to behave any differently. Yes, in the MWE I should have switched it to \newcommand, but I need \providecommand in my real usage. – Peter Grill Jun 06 '11 at 18:22
  • @Peter: really? To me it does exactly what you want. I'll edit the answer with the complete definition. – egreg Jun 06 '11 at 19:57
  • Only reason I would want to be able to call \DefinedNamedFunction{FunctionFF}{$y=x$} (with the dollar signs) as it is more natural to do so. I didn't want to have to remember that when I use this macro I do not put the $$, but for all the other macros where I have math, I do put the $$. – Peter Grill Jun 06 '11 at 20:16
  • This solution using DNFnorm looks simpler. – Peter Grill Jun 06 '11 at 20:45
  • @Peter: it's just a command defined for the purpose. It checks whether #2 starts with $; in this case it is substituted by \DNFnormi that throws away the two $, otherwise it does nothing. – egreg Jun 06 '11 at 20:51
  • @egreg: Thanks. I realized that and tried to edit my comment in time, but you were too quick. Thanks, I can actually understand this solution and customize it for me needs. Works great so far. – Peter Grill Jun 06 '11 at 20:58
2
\documentclass{article}
\usepackage{amsmath}
\usepackage{xcolor}
\makeatletter
\def\DefineNamedFunction#1#2{\expandafter\DefineNamedFunction@i#1\@nil#2\@nil}
\def\DefineNamedFunction@i#1\@nil{%
  \@ifnextchar${\DefineNamedFunction@ii{#1}}{\DefineNamedFunction@iii{#1}}}
\def\DefineNamedFunction@ii#1$#2$\@nil{%
  \@namedef{#1}{\ifmmode\textcolor{red}{#2}\else\textcolor{red}{$#2$}\fi}}
\def\DefineNamedFunction@iii#1#2\@nil{%
  \@namedef{#1}{\ifmmode\textcolor{red}{#2}\else\textcolor{red}{$#2$}\fi}}
\makeatother

\DefineNamedFunction{FunctionF}{y = 2 \sin x}
\DefineNamedFunction{FunctionFF}{$y = 2 \sin x$}
\begin{document}    
I can use \FunctionF\ inside math mode as $\FunctionF$,
but can also use this outside of math mode as 
$\FunctionFF$ and \FunctionFF.

\end{document}
  • This works great. Thanks. So, is this basically doing the job of \ensuremath manually? – Peter Grill Jun 06 '11 at 18:27
  • more or less ... the problem is \textcolor when it is used in math mode with a math argument –  Jun 06 '11 at 18:30
  • @Herbert: apart from making the + an ordinary atom, $\textcolor{blue}{a}\textcolor{red}{+}\textcolor{green}{b}$ works perfectly. – egreg Jun 06 '11 at 20:08
  • @egreg: I was talking about $\textcolor{blue}{$a$}$ ... –  Jun 07 '11 at 04:25
  • @Herbert: I see; \textcolor is smart enough to know when it's called in math mode: maybe a pair \textcolor and \mathcolor would have been better. – egreg Jun 07 '11 at 08:16
  • @egreg: I meant this: $\DefineNamedFunction{FunctionFFF}{$y = 2 \sin x$}\FunctionFFF$ –  Jun 07 '11 at 08:20
  • @Herbert: that would be a very devious way. With my macros it works. – egreg Jun 07 '11 at 08:26
  • @egreg: I never said, that it wouldn't work with your solution ... –  Jun 07 '11 at 08:43