X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/a6ec8b3f5bd19ad4a2a6fc950639cdff196eea2c..7d8d3a165fa725b686d1c89b78179a4d5705d11a:/doc/sod.sty

diff --git a/doc/sod.sty b/doc/sod.sty
index 4d2f407..44fe07a 100644
--- a/doc/sod.sty
+++ b/doc/sod.sty
@@ -237,6 +237,41 @@
 %% Show a backslash by the right-hand margin; for multiline macros etc.
 \def\macsl{\`\textbackslash\hskip\leftmargin}
 
+%% \maplist{THING}{{ITEM}...}: Invoke THING{ITEM} for each ITEM in turn.
+\def\maplist#1#2{\map@i{#1}#2\q@}
+\def\map@i#1{\def\next@{\map@ii{#1}}\futurelet\ch@\next@}
+\def\map@ii#1{\ifx\ch@\q@\expandafter\@gobble%
+  \else\def\next@{\map@iii{#1}}\expandafter\next@\fi}
+\def\map@iii#1#2{#1{#2}\map@i{#1}}
+
+%% \crossproduct{THING}{{LIST}...} where each LIST is {ITEM}...
+%% For each possible way of selecting one ITEM from each LIST, in order,
+%% invoke THING{{ITEM}...}
+\toksdef\cprod@new=0
+\toksdef\cprod@old=2
+\toksdef\cprod@head=4
+\toksdef\cprod@tail=6
+\def\crossproduct#1#2{%
+  \cprod@new{{}}%
+  \maplist{\cprod@f{#1}}{#2}%
+  \cprod@head{#1}%
+  \edef\next@{\noexpand\maplist{\the\cprod@head}{\the\cprod@new}}
+  \next@%
+}
+\def\cprod@f#1#2{%
+  \cprod@old\cprod@new\cprod@new{}%
+  \maplist\cprod@g{#2}%
+}
+\def\cprod@g#1{%
+  \cprod@head{#1}%
+  \expandafter\maplist\expandafter\cprod@h\expandafter{\the\cprod@old}%
+}
+\def\cprod@h#1{%
+  \cprod@tail{#1}%
+  \cprod@new\expandafter{\the\expandafter\cprod@new\expandafter{%
+      \the\expandafter\cprod@tail\the\cprod@head}}%
+}
+
 %%%--------------------------------------------------------------------------
 %%% Machinery for describing functions, etc.
 
