# Non letter name in command definition

I'd like to define similar commands one with underscore the other — without. However such an approach throws me an error

\def\Fix#1{\mathrm{Fix}(#1)}
\def\Fix_#1#2{\mathrm{Fix}_{\,#1}(#2)}


I tried to change the catcode of the underscore and set it back, but \Fix_ seemed to work exactly like \Fix

\def\Fix#1{\mathrm{Fix}(#1)}
\catcode\_=11
\def\Fix_#1#2{\mathrm{Fix}_{\,#1}(#2)}
\catcode\_=8


What is the right way to do that?

Your first approach doesn't work because TeX can't have two definitions for the same command, so the second definition overwrites the first. Your second approach kind-of works because you have two commands, \Fix and \Fix_, but you cannot access \Fix_ normally.

You have to define \Fix to look ahead for an optional _. For example, with \@ifnextchar:

\documentclass{article}
\makeatletter
\DeclareRobustCommand\Fix{\@ifnextchar_{\@FixU}{\@Fix}}
\def\@Fix#1{\mathrm{Fix}(#1)}
\def\@FixU_#1#2{\mathrm{Fix}_{\,#1}(#2)}
\makeatother
\begin{document}
$\Fix{a}$ and $\Fix_{b}{a}$
\end{document}


Or, much easier (and robust), with xparse:

\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand\Fix { e{_} m }
{\mathrm{Fix}\IfValueT{#1}{_{\,#1}}(#2)}
\begin{document}
$\Fix{a}$ and $\Fix_{b}{a}$
\end{document}


Both documents produce:

• Thank you for the detailed explanation why my attempts didn't work and for your solutions. I do especially like the xparse one. – antshar May 4 at 15:15
• @antshar You're welcome! The e argument type for xparse is especially powerful if you have two tokens, for example _ and ^ (for example \NewDocumentCommand\Fix { e{_^} m }{\mathrm{Fix}\IfValueT{#1}{_{\,#1}}\IfValueT{#2}{^{\,#2}}(#3)}) then when you use the command you can have the arguments in any order (you could use the command above with $\Fix^{c}_{b}{a}$ or $\Fix_{b}^{c}{a}$). – Phelype Oleinik May 4 at 15:19