The command \DEFINEbbANDmcANDmsANDmfLOOP is intended to process an undelimited argument which consists of exactly one token. It checks whether its argument's first token's meaning equals the meaning of the \relax-primitive.
If so, it swallows the following action via \@gobble.
If not so it assumes that the argument is a single character token denoting a ⟨letter⟩ and performs the following action via \@firstofone:
- define the macro
\bb⟨letter⟩ to expand to \mathbb{⟨letter⟩}
- define the macro
\mc⟨letter⟩ to expand to \mathcal{⟨letter⟩}
- define the macro
\ms⟨letter⟩ to expand to \mathscr{⟨letter⟩}
- define the macro
\mf⟨letter⟩ to expand to \mathfrakr{⟨letter⟩}
- call itself again.
The concept of a macro calling itself again for applying the same action to another argument is called tail-recursion.
(For defining the macros I have implemented a little helper-macro \CmdName which works as follows:
\CmdName⟨stuff without braces⟩{macroname} → ⟨stuff without braces⟩\macroname.
Examples:
\CmdName\newcommand*{foobar}... → \newcommand*\foobar....
I use \CmdName when I am not in the mood for typing \expandafter and \csname..\endcsname so often. ;-) )
\documentclass{article}
\makeatletter
@ifdefinable\CmdName{\long\def\CmdName#1#{\romannumeral0\innerCmdName{#1}}}%
\newcommand\innerCmdName[2]{\expandafter\exchange\expandafter{\csname #2\endcsname}{ #1}}%
\newcommand\exchange[2]{#2#1}%
\newcommand\DEFINEbbANDmcANDmsANDmfLOOP[1]{%
\ifx\relax#1\expandafter@gobble\else\expandafter@firstofone\fi
{%
\CmdName\newcommand{bb#1}{\mathbb{#1}}%
\CmdName\newcommand{mc#1}{\mathcal{#1}}%
\CmdName\newcommand{ms#1}{\mathscr{#1}}%
\CmdName\newcommand{mf#1}{\mathfrak{#1}}%
\DEFINEbbANDmcANDmsANDmfLOOP
}%
}%
\makeatother
% Now for each of the letters define \bb<letter>, \mc<letter>, \ms<letter> and \mf<letter>:
\DEFINEbbANDmcANDmsANDmfLOOP abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\relax
\begin{document}
\show\bba
\show\mca
\show\msa
\show\mfa
\show\bbb
\show\mcb
\show\msb
\show\mfb
% .
% .
% .
% .
\show\bbY
\show\mcY
\show\msY
\show\mfY
\show\bbZ
\show\mcZ
\show\msZ
\show\mfZ
\end{document}
If you like, you can apply tail-recursion with a macro \Definealphabet:
\documentclass{article}
\makeatletter
\newcommand\DEFINEALPHABETLOOP[3]{%
\ifx\relax#3\expandafter@gobble\else\expandafter@firstofone\fi
{\expandafter\newcommand\expandafter*\csname#1#3\endcsname{#2{#3}}%
\DEFINEALPHABETLOOP{#1}{#2}}%
}%
\newcommand\Definealphabet[2]{%
\DEFINEALPHABETLOOP{#1}{#2}abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\relax
}%
\makeatother
\Definealphabet{bb}{\mathbb}
\Definealphabet{mc}{\mathcal}
\Definealphabet{ms}{\mathscr}
\Definealphabet{mf}{\mathfrak}
\begin{document}
\show\bba
% ...
\show\bbz
\show\mca
% ...
\show\mcz
\show\msa
% ...
\show\msz
\show\mfa
% ...
\show\mfz
\end{document}
If you need a TeX-⟨number⟩-quantity which denotes the character-code of a charcter in the internal character-representation-scheme of TeX, you can use alphabetic constants.
E.g., both `A and `\A denotes the character code of the character A.
The further is not "\lowercase-proof".
The latter in the context of macro-programming might not be proof against the control sequence token behind ` being \outer.
Also be aware that TeX scans for one optional space with the last token of an alphabetic constant.
Thus, if you like, you can as well implement a tail-recursive loop, where \csname..\endcsname is combined with \lccode/\lowercase-trickery for looping over the alphabet, and where you can specify slash-separated phrases for the math-alphabet-command to call and for the names of the commands to define the prefix before the alphabetical letter and the postfix behind the alphabetical letter:
\documentclass{article}
\makeatletter
\newcommand\PassFirstToSecond[2]{#2{#1}}%
@ifdefinable\SlashFirstOfThree{\long\def\SlashFirstOfThree#1/#2/#3/{#1}}%
@ifdefinable\SlashArgBetweenSecondAndThirdOfThree{\long\def\SlashArgBetweenSecondAndThirdOfThree#1#2/#3/#4/{#3#1#4}}%
\newcommand\DefineAlphabetsLoop[1]{\DefineAlphabetsLoopInner{\A}#1\relax}% \newcommand\DefineAlphabetsLoopInner[2]{% % #1 - character-code of character wherefore macro is to be defined; #2 - slash-separated triple of phrases: % of pattern % <math-alphabet-macro to call>/<prefix before alphabet-letter of name of macro to define>/<prefix after alphabet-letter of name of macro to define> \ifx\relax#2\expandafter\@gobble\else\expandafter\@firstofone\fi{% \ifnum#1>\@firstofone{\z} \expandafter@secondoftwo\else\expandafter@firstoftwo\fi
%@ifundefined{\SlashArgBetweenSecondAndThirdOfThree{z}#2/}%
{%
\begingroup
\lccode\m=#1\relax \lowercase\expandafter{\expandafter\PassFirstToSecond\expandafter{\SlashFirstOfThree#2/{m}}}% {% \lowercase{\PassFirstToSecond{m}}% {\endgroup\expandafter\newcommand\expandafter*\csname\SlashArgBetweenSecondAndThirdOfThree}#2/\endcsname }% \expandafter\DefineAlphabetsLoopInner\expandafter{\the\numexpr\ifnum#1=\Z\a\else(#1)+1\fi\relax}{#2}% }{% \DefineAlphabetsLoopInner{\A}%
}%
}%
}%
\makeatother
\begin{document}
%-------------------------------------------------------------------------------------
% Only prefix:
\DefineAlphabetsLoop{{\mathbb/bb/}{\mathcal/mc/}{\mathscr/ms/}{\mathfrak/mf/}}%
\show\bbA \show\mcA \show\msA \show\mfA
\show\bbB \show\mcB \show\msB \show\mfB
\show\bbY \show\mcY \show\msY \show\mfY
\show\bbZ \show\mcZ \show\msZ \show\mfZ
% .
% .
% .
% .
\show\bba \show\mca \show\msa \show\mfa
\show\bbb \show\mcb \show\msb \show\mfb
\show\bby \show\mcy \show\msy \show\mfy
\show\bbz \show\mcz \show\msz \show\mfz
%-------------------------------------------------------------------------------------
% Only postfix:
% Of course you get: ! LaTeX Error: Command \bbb already defined.
% That's because \bbb was defined by the prevous loop.
\DefineAlphabetsLoop{{\mathbb//bb}{\mathcal//mc}{\mathscr//ms}{\mathfrak//mf}}%
\show\Abb \show\Amc \show\Ams \show\Amf
\show\Bbb \show\Bmc \show\Bms \show\Bmf
\show\Ybb \show\Ymc \show\Yms \show\Ymf
\show\Zbb \show\Zmc \show\Zms \show\Zmf
% .
% .
% .
% .
\show\abb \show\amc \show\ams \show\amf
\show\bbb \show\bmc \show\bms \show\bmf
\show\ybb \show\ymc \show\yms \show\ymf
\show\zbb \show\zmc \show\zms \show\zmf
%-------------------------------------------------------------------------------------
% Both prefix and postfix:
\DefineAlphabetsLoop{{\mathbb/bb/bb}{\mathcal/mc/mc}{\mathscr/ms/ms}{\mathfrak/mf/mf}}%
\show\bbAbb \show\mcAmc \show\msAms \show\mfAmf
\show\bbBbb \show\mcBmc \show\msBms \show\mfBmf
\show\bbYbb \show\mcYmc \show\msYms \show\mfYmf
\show\bbZbb \show\mcZmc \show\msZms \show\mfZmf
% .
% .
% .
% .
\show\bbabb \show\mcamc \show\msams \show\mfamf
\show\bbbbb \show\mcbmc \show\msbms \show\mfbmf
\show\bbybb \show\mcymc \show\msyms \show\mfymf
\show\bbzbb \show\mczmc \show\mszms \show\mfzmf
%-------------------------------------------------------------------------------------
% Of course, instead of having three \DefineAlphabetsLoop, you could
% as well have done:
%
% \DefineAlphabetsLoop{%
% {\mathbb/bb/}{\mathcal/mc/}{\mathscr/ms/}{\mathfrak/mf/}%
% {\mathbb//bb}{\mathcal//mc}{\mathscr//ms}{\mathfrak//mf}%
% {\mathbb/bb/bb}{\mathcal/mc/mc}{\mathscr/ms/ms}{\mathfrak/mf/mf}%
% }%
\end{document}
A slightly more generic variant could be:
\alphabetloop{<stuff>} by and by does: <stuff>{A}...<stuff>{Z}<stuff>{a}...<stuff>{z}
and
\LoopEachOverAlphabet{<stuff prefix>}{<stuff postfix>}{%
{<stuff 1>}%
{<stuff 2>}%
%...
{<stuff n>}%
}%
by and by does
\alphabetloop{<stuff prefix><stuff 1><stuff postfix>}%
\alphabetloop{<stuff prefix><stuff 2><stuff postfix>}%
...
\alphabetloop{<stuff prefix><stuff n><stuff postfix>}%
, which by and by turns into
<stuff prefix><stuff 1><stuff postfix>{A}...<stuff prefix><stuff 1><stuff postfix>{Z}<stuff prefix><stuff 1><stuff postfix>{a}...<stuff prefix><stuff 1><stuff postfix>{z}%
<stuff prefix><stuff 2><stuff postfix>{A}...<stuff prefix><stuff 2><stuff postfix>{Z}<stuff prefix><stuff 2><stuff postfix>{a}...<stuff prefix><stuff 2><stuff postfix>{z}%
%...
<stuff prefix><stuff n><stuff postfix>{A}...<stuff prefix><stuff n><stuff postfix>{Z}<stuff prefix><stuff n><stuff postfix>{a}...<stuff prefix><stuff n><stuff postfix>{z}%
.
\documentclass{article}
\makeatletter
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand\alphabetloop{\alphabetloopinner{\A}}% \newcommand\alphabetloopinner[2]{% \ifnum#1>\@firstofone{\z} \expandafter@gobble\else\expandafter@firstofone\fi
{%
\begingroup
\lccode\m=#1\relax \lowercase{\PassFirstToSecond{m}}{\endgroup#2}% \expandafter\alphabetloopinner\expandafter{\the\numexpr\ifnum#1=\Z`\a\else(#1)+1\fi\relax}{#2}%
}%
}%
\newcommand\LoopEachOverAlphabet[3]{\LoopEachOverAlphabetInner{#1}{#2}#3\relax}%
\newcommand\LoopEachOverAlphabetInner[3]{%
\ifx\relax#3\expandafter@gobble\else\expandafter@firstofone\fi{%
\alphabetloop{#1#3#2}%
\LoopEachOverAlphabetInner{#1}{#2}%
}%
}%
@ifdefinable\definealphabetmacro{%
\long\def\definealphabetmacro#1/#2/#3/#4{\expandafter\newcommand\expandafter*\csname #2#4#3\endcsname{#1{#4}}}%
}%
\newcommand\DefineAlphabetMacros{%
\LoopEachOverAlphabet{\definealphabetmacro}{/}%
}%
\makeatother
\newcommand\showalphabetmacro[3]{%
\expandafter\show\csname #1#3#2\endcsname
}%
\begin{document}
%-------------------------------------------------------------------------------------
% Only prefix:
\DefineAlphabetMacros{{\mathbb/bb/}{\mathcal/mc/}{\mathscr/ms/}{\mathfrak/mf/}}%
%-------------------------------------------------------------------------------------
% Only postfix:
% Of course you get: ! LaTeX Error: Command \bbb already defined.
% That's because \bbb was defined by the prevous loop.
\DefineAlphabetMacros{{\mathbb//bb}{\mathcal//mc}{\mathscr//ms}{\mathfrak//mf}}%
%-------------------------------------------------------------------------------------
% Both prefix and postfix:
\DefineAlphabetMacros{{\mathbb/bb/bb}{\mathcal/mc/mc}{\mathscr/ms/ms}{\mathfrak/mf/mf}}%
%-------------------------------------------------------------------------------------
% Of course, instead of having three \DefineAlphabetsLoop, you could
% as well have done:
%
% \DefineAlphabetMacros{%
% {\mathbb/bb/}{\mathcal/mc/}{\mathscr/ms/}{\mathfrak/mf/}%
% {\mathbb//bb}{\mathcal//mc}{\mathscr//ms}{\mathfrak//mf}%
% {\mathbb/bb/bb}{\mathcal/mc/mc}{\mathscr/ms/ms}{\mathfrak/mf/mf}%
% }%
% This does \show 12*52 = 624 times. \bbb is shown twice:
\def\scratch{0}
\LoopEachOverAlphabet{%
\edef\scratch{\the\numexpr\scratch+1\relax}%
\message{^^JIteration \scratch:^^J}%
\showalphabetmacro
}{}{%
{{bb}{}} {{mc}{}} {{ms}{}} {{mf}{}}
{{}{bb}} {{}{mc}} {{}{ms}} {{}{mf}}
{{bb}{bb}} {{mc}{mc}} {{ms}{ms}} {{mf}{mf}}
}%
\end{document}
\newcommand\mf{\mathfrak}then use\mf Adefining all the extra commands seems totally unnecessary. – David Carlisle Sep 25 '20 at 20:20