Introduce many new commands

What you are looking for is the plain-TeX directive \csname...\endcsname (cs for "control sequence"). Whereas the \<macro-name> syntax requires that the macro name be a predefined sequence of catcode 11 letters, what goes between the \csname...\endcsname delimiters can include symbols of other catcodes, and can include variables evaluated at the time of invocation.

The only trick, beyond this, is to use \expandafter prior to the defining \newcommand, so that the \csname gets expanded into the actual control sequence.

\documentclass{article}
\newcommand{\declaresymbols}[2]{\expandafter\newcommand\csname#1term\endcsname{t^{#2}}}
\begin{document}
\declaresymbols{a}{\alpha}
\declaresymbols{b}{\beta}

$\aterm \ne \bterm$
\end{document}

enter image description here

If you do a lot of work in the cs domain of programming, packages like etoolbox are extremely useful, providing whole families of macros for working with this tricky syntax in more natural ways.


You can do with

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand\definesymbol{omm}
 {
  \IfNoValueTF{#1}
   { \cs_new:cpn {#2} { #3 } }
   { \cs_new:cpn { #2 #1 } { \use:c { #1 } \sp { #3 } } }
 }
\ExplSyntaxOff

\definesymbol{term}{t}
\definesymbol[term]{a}{\alpha}
\definesymbol[term]{b}{\beta}

\definesymbol{X}{X}
\definesymbol[X]{a}{a}

\begin{document}

$\term+\aterm+\bterm+\X+\aX$

\end{document}

The call without the optional argument defines the main macro, with the optional argument it adds the superscripts and the prefix.

enter image description here


Since Ulrich Diez launched a contest, here it is a solution similar to his, but with much less code and a friendlier syntax.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\cs_new_protected:Nn \choeger_declare_single_symbol:nnnnnn
 {
  % {<macro-name of base-symbol>}
  % {<coding of base symbol>}
  % {<symbol-macro-name-prefix>}
  % {<symbol-macro-name-postfix>}
  % {<coding of preceding operands and operators>}
  % {<coding of trailing operands and operators>}
  \cs_new_protected:cpn { #3#1#4 } { #5{#2}#6 }
 }

\cs_new_protected:Nn \choeger_declare_symbol_family:nnn
 {
  % {<macro-name of base-symbol>}
  % {<coding of base symbol>}
  % {<list of sequences {prefix}{postfix}{prefix code}{postfix code}>}

  % define the base symbol
  \cs_new_protected:cpn { #1 } { {#2} }
  % define the others
  \clist_map_inline:nn { #3 }
   {
    \choeger_declare_single_symbol:nnnnnn { #1 } { #2 } ##1
   }
 }

\cs_new_protected:Nn \choeger_declare_symbol_families:nn
 {
  % {<list of sequences {name}{code}>}
  % {<list of sequences {prefix}{postfix}{prefix code}{postfix code}>}
  \clist_map_inline:nn { #1 }
   {
    \choeger_declare_symbol_family:nnn ##1 { #2 }
   }
 }

\NewDocumentCommand{\DeclareSymbolFamilies}{mm}
 {
  \choeger_declare_symbol_families:nn { #1 } { #2 }
 }

\ExplSyntaxOff

\DeclareSymbolFamilies
 {
  {Foo}{\langle\mathit{Foo}\rangle},
  {Term}{t},
  {Val}{v},
 }
 {
  {}{RaisedToPowerAlpha}{}{^\alpha},
  {MultiplyBetaWith}{}{\beta\cdot}{},
  {}{MultipiedWithGamma}{}{\cdot\gamma},
  {RaiseDeltaToThePowerOf}{}{\delta^}{},
  {MultiplyBetaWith}{AndAddTwo}{\beta\cdot}{+2},
  {MultiplyBetaWith}{AfterAddingTwo}{\beta\cdot(}{+2)},
  {DivideBetaBy}{}{\left(\frac{\beta}}{\right)},
  {Divide}{ByBeta}{\left(\frac}{{\beta}\right)},  
 }

\begin{document}
\setlength{\parindent}{0pt}

\verb|\Foo|: $\Foo$\\
\verb|\FooRaisedToPowerAlpha|: $\FooRaisedToPowerAlpha$\\
\verb|\MultiplyBetaWithFoo|: $\MultiplyBetaWithFoo$\\
\verb|\FooMultipiedWithGamma|: $\FooMultipiedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfFoo|: $\RaiseDeltaToThePowerOfFoo$\\
\verb|\MultiplyBetaWithFooAndAddTwo|: $\MultiplyBetaWithFooAndAddTwo$\\
\verb|\MultiplyBetaWithFooAfterAddingTwo|: $\MultiplyBetaWithFooAfterAddingTwo$\\
\verb|\DivideBetaByFoo|: $\DivideBetaByFoo$\\
\verb|\DivideFooByBeta|: $\DivideFooByBeta$

\bigskip

\verb|\Term|: $\Term$\\
\verb|\TermRaisedToPowerAlpha|: $\TermRaisedToPowerAlpha$\\
\verb|\MultiplyBetaWithTerm|: $\MultiplyBetaWithTerm$\\
\verb|\TermMultipiedWithGamma|: $\TermMultipiedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfTerm|: $\RaiseDeltaToThePowerOfTerm$\\
\verb|\MultiplyBetaWithTermAndAddTwo|: $\MultiplyBetaWithTermAndAddTwo$\\
\verb|\MultiplyBetaWithTermAfterAddingTwo|: $\MultiplyBetaWithTermAfterAddingTwo$\\
\verb|\DivideBetaByTerm|: $\DivideBetaByTerm$\\
\verb|\DivideTermByBeta|: $\DivideTermByBeta$

\bigskip

\verb|\Val|: $\Val$\\
\verb|\ValRaisedToPowerAlpha|: $\ValRaisedToPowerAlpha$\\
\verb|\MultiplyBetaWithVal|: $\MultiplyBetaWithVal$\\
\verb|\ValMultipiedWithGamma|: $\ValMultipiedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfVal|: $\RaiseDeltaToThePowerOfVal$\\
\verb|\MultiplyBetaWithValAndAddTwo|: $\MultiplyBetaWithValAndAddTwo$\\
\verb|\MultiplyBetaWithValAfterAddingTwo|: $\MultiplyBetaWithValAfterAddingTwo$\\
\verb|\DivideBetaByVal|: $\DivideBetaByVal$\\
\verb|\DivideValByBeta|: $\DivideValByBeta$

\end{document}

Some nested loops might do the trick:

\documentclass{article}
\usepackage{amsmath, textcomp}

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% A concern in his posting is that the argument is hit with \string
%% after some expansions which in edge cases might result in unbalancing
%% surrounding \if..\fi-constructs if the macro is used inside of such
%% \if..\fi-constructs.
%%
%% That challenging concern sickened me. ;-)
%%
%% Therefore I decided to implerment a variant where this cannot happen
%% as expansion is forced by \romannumeral:
%%
%% After the first expansion-step, \string is not applied yet.
%% After the second expansion-step, any possibly disturbing remainders
%% are already removed due to \romannumeral-expansion.
%%
%% No eTeX- or whatsoever extensions. No \if.. .Only \romannumeral,
%% digit 0, space token for terminating \romannumeral-expansion,
%% \string, \expandafter, \@firstoftwo, \@secondoftwo, {, }.
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
  \@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Fully expandable for-loop:
%%.............................................................................
%% \UD@DoWithEachElementOfArgumentList{<action>}%
%%                             {<action when no (more) arguments are in list>}%
%%                             {<preset>}%
%%                             {{<e_k>}{<e_(k+1)>}..{<e_n>}}
%%
%%  yields (after two expansion-steps) :
%%
%%  <action>{<e_k>}<preset>%
%%  <action>{<e_(k+1)>}<preset>%
%%  ...
%%  <action>{<e_n>}<preset>%
%%  <action when no (more) arguments are in list>%
%%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@KeepOnlyFirstBeforeSeLDoM{}%
\long\def\UD@KeepOnlyFirstBeforeSeLDoM#1#2\SeLDoM{{#1}}%
\newcommand\UD@DoWithEachElementOfArgumentList{%
  \romannumeral0\UD@MoveElementFromList{}{ }%
}%
\newcommand\UD@MoveElementFromList[6]{%
  \UD@CheckWhetherNull{#1}{%
    \expandafter\UD@CheckWhetherNull\expandafter{\@secondoftwo#6.{}}{#2#4}{%
      \expandafter\expandafter\expandafter\UD@MoveElementFromList
      \expandafter\UD@Exchange
      \expandafter{%
      \expandafter{\@firstoftwo{}#6}}{{#6\SeLDoM}{#2}{#3}{#4}{#5}}%
    }%
  }{%
    \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
    {\UD@MoveElementFromList{}{#2#3#1#5}}%
    {\expandafter\UD@MoveElementFromList
     \expandafter{\UD@KeepOnlyFirstBeforeSeLDoM#1}{#2}%
    }{#3}{#4}{#5}{#6}%
  }%
}%

%%-----------------------------------------------------------------------------
%% \DeclareASingleSymbol{<symbol-macro-name-prefix>}%
%%                      {<symbol-macro-name-postfix>}%
%%                      {<coding of base symbol / coding of preceding operands and operators>}%
%%                      {<coding of trailing operands and operators>}%
%%                      {<macro-name of base-symbol>}
%%.............................................................................
\newcommand\DeclareASingleSymbol[5]{%
  \UD@CheckWhetherNull{#1#2}{%
    \expandafter\newcommand\csname#5\endcsname{#3}%
  }{%
    \expandafter\newcommand\csname#1#5#2%
    \expandafter\expandafter\expandafter\expandafter
    \expandafter\expandafter\expandafter\endcsname
    \expandafter\expandafter\expandafter\expandafter
    \expandafter\expandafter\expandafter{%
    \expandafter\expandafter\expandafter\UD@Exchange
    \expandafter\expandafter\expandafter{%
    \csname#5\endcsname#4}{#3}}%
  }%
}%
%%-----------------------------------------------------------------------------
%% \DeclareOneSymbolFamily
%%   {<macro-name of base-symbol>}%
%%   {<coding of base-symbol>}%
%%   {%
%%     {{<symbol-macro-name-prefix 1>}{<symbol-macro-name-postfix 1>}{<coding of preceding operands and operators 1>}{<coding of trailing operands and operators 1>}}%
%%     {{<symbol-macro-name-prefix 2>}{<symbol-macro-name-postfix 2>}{<coding of preceding operands and operators 2>}{<coding of trailing operands and operators 2>}}%
%%    ..
%%     {{<symbol-macro-name-prefix n>}{<symbol-macro-name-postfix n>}{<coding of preceding operands and operators n>}{<coding of trailing operands and operators n>}}%
%%   }%
%%
%%.............................................................................
\newcommand\DeclareOneSymbolFamily[3]{%
   \UD@DoWithEachElementOfArgumentList{\expandafter\DeclareASingleSymbol\@firstofone}%
                                      {}%
                                      {{#1}}%
                                      {{{}{}{#2}{}}#3}%
}%
%%-----------------------------------------------------------------------------
%% \DeclareSeveralSymbolFamilies{%
%%   {{<macro-name of base-symbol 1>}{<coding of base-symbol 1>}%
%%   {{<macro-name of base-symbol 2>}{<coding of base-symbol 2>}}%
%5   ..
%%   {{<macro-name of base-symbol k>}{<coding of base-symbol k>}}%
%% }{%
%%     {{<symbol-macro-name-prefix 1>}{<symbol-macro-name-postfix 1>}{<coding of preceding operands and operators 1>}{<coding of trailing operands and operators 1>}}%
%%     {{<symbol-macro-name-prefix 2>}{<symbol-macro-name-postfix 2>}{<coding of preceding operands and operators 2>}{<coding of trailing operands and operators 2>}}%
%%    ..
%%     {{<symbol-macro-name-prefix n>}{<symbol-macro-name-postfix n>}{<coding of preceding operands and operators n>}{<coding of trailing operands and operators n>}}%
%% }
%%
%%.............................................................................
\newcommand\DeclareSeveralSymbolFamilies[2]{%
   \UD@DoWithEachElementOfArgumentList{\expandafter\DeclareOneSymbolFamily\@firstofone}%
                                       {}%
                                       {{#2}}%
                                       {#1}%
}%

\makeatother

\DeclareSeveralSymbolFamilies{%
  {{Foo}{{\mathit{\text{\textlangle}Foo\text{\textrangle}}}}}%
  {{Term}{t}}%
  {{Val}{v}}%
}{%
  {{}{RaisedToPowerAlpha}{}{^\alpha}}%
  {{MulitplyBetaWith}{}{\beta\cdot}{}}%
  {{}{MulipliedWithGamma}{}{\cdot\gamma}}%
  {{RaiseDeltaToThePowerOf}{}{\delta^}{}}%
  {{MulitplyBetaWith}{AndAddTwo}{\beta\cdot}{+2}}%
  {{MulitplyBetaWith}{AfterAddingTwo}{\beta\cdot(}{+2)}}%
  {{DivideBetaBy}{}{\left(\frac{\beta}}{\right)}}%
  {{Divide}{ByBeta}{\left(\frac}{{\beta}\right)}}%  
}%

\begin{document}


\verb|\Foo|: $\Foo$\\
\verb|\FooRaisedToPowerAlpha|: $\FooRaisedToPowerAlpha$\\
\verb|\MulitplyBetaWithFoo|: $\MulitplyBetaWithFoo$\\
\verb|\FooMulipliedWithGamma|: $\FooMulipliedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfFoo|: $\RaiseDeltaToThePowerOfFoo$\\
\verb|\MulitplyBetaWithFooAndAddTwo|: $\MulitplyBetaWithFooAndAddTwo$\\
\verb|\MulitplyBetaWithFooAfterAddingTwo|: $\MulitplyBetaWithFooAfterAddingTwo$\\
\verb|\DivideBetaByFoo|: $\DivideBetaByFoo$\\
\verb|\DivideFooByBeta|: $\DivideFooByBeta$\\


\verb|\Term|: $\Term$\\
\verb|\TermRaisedToPowerAlpha|: $\TermRaisedToPowerAlpha$\\
\verb|\MulitplyBetaWithTerm|: $\MulitplyBetaWithTerm$\\
\verb|\TermMulipliedWithGamma|: $\TermMulipliedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfTerm|: $\RaiseDeltaToThePowerOfTerm$\\
\verb|\MulitplyBetaWithTermAndAddTwo|: $\MulitplyBetaWithTermAndAddTwo$\\
\verb|\MulitplyBetaWithTermAfterAddingTwo|: $\MulitplyBetaWithTermAfterAddingTwo$\\
\verb|\DivideBetaByTerm|: $\DivideBetaByTerm$\\
\verb|\DivideTermByBeta|: $\DivideTermByBeta$\\


\verb|\Val|: $\Val$\\
\verb|\ValRaisedToPowerAlpha|: $\ValRaisedToPowerAlpha$\\
\verb|\MulitplyBetaWithVal|: $\MulitplyBetaWithVal$\\
\verb|\ValMulipliedWithGamma|: $\ValMulipliedWithGamma$\\
\verb|\RaiseDeltaToThePowerOfVal|: $\RaiseDeltaToThePowerOfVal$\\
\verb|\MulitplyBetaWithValAndAddTwo|: $\MulitplyBetaWithValAndAddTwo$\\
\verb|\MulitplyBetaWithValAfterAddingTwo|: $\MulitplyBetaWithValAfterAddingTwo$\\
\verb|\DivideBetaByVal|: $\DivideBetaByVal$\\
\verb|\DivideValByBeta|: $\DivideValByBeta$\\

\end{document}                 

Tags:

Macros