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