Llamar a un comando con un argumento opcional generado

Llamar a un comando con un argumento opcional generado

Estoy trabajando en una macro que debería ahorrarme mucho tiempo en el futuro. Actualmente tengo funcionando uno de los comandos que quería, pero tengo problemas para que funcione la segunda parte. Ese primer comando se define de la siguiente manera:

\NewDocumentCommand\x
{
    s
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
}{
  % Full definition of the command
}

Este comando toma ocho argumentos opcionales, cada uno es una lista separada por comas, generalmente números, aunque no es necesario. Podría llamarlo como \x[-3,0][0,-2]o \x[1,2,3,0][4,5,6,0][7,8,9,0]. Cada lista siempre tendrá la misma longitud.

Estoy intentando crear un segundo comando que actúe un poco como una transposición. Por lo tanto, también se necesitan hasta ocho listas, pero estas listas están separadas con estrellas y los elementos son listas del \xcomando. Es más fácil mostrar con un ejemplo cómo funciona:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]

sería equivalente a:

\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]

Cada una de estas listas de estrellas tendría la misma cantidad de elementos. Si tuvieran diferentes números de elementos o elementos que no fueran argumentos del \xcomando entonces podría pasar cualquier cosa, un error, insertar algún tipo de elemento nulo, truncar a la lista más corta, etc. No se llamará de esa manera, por lo que no No importa.

La longitud de estas listas es la cantidad de \xllamadas que hay. En este ejemplo, la longitud es tres, por lo que hay tres llamadas a, \xpero si la longitud fuera mayor o menor habría un número diferente. El número de listas es el número de argumentos que hay para cada llamada de \x. En este ejemplo, hay dos pero podrían haber hasta 8.

Si es posible, me gustaría poder pasar una estrella de \mxm*a, \x*pero si eso es demasiado difícil, tengo una solución alternativa, ya que no debería aparecer con mucha frecuencia. Así es como se vería:

\mxm[[1,3,1]*[-1, 0,3]]
    [[2,2,1]*[ 0,-2,2]]
    [[3,1,2]*[ 1,-2,1]]

sería equivalente a:

\x*[1,3,1]
   [2,2,1]
   [3,1,2]
\x*[-1, 0,3]
   [ 0,-2,2]
   [ 1,-2,1]

Aquí hay un MWEcon un ejemplo \x(solo un marcador de posición, no se puede llamar \x). También incluye hasta dónde llegué, aunque no creo que sea de mucha ayuda.

Respuesta1

La recursividad de cola, es decir, macros que se llaman a sí mismas nuevamente y mucho intercambio de argumentos de antemano, podrían ser la solución. ;-)

Si lo hago bien, \mxmes procesar una lista de argumentos opcionales de los cuales cada argumento opcional contiene una *lista separada de argumentos opcionales.

No especificó qué hacer en caso de que no todas *las listas separadas de argumentos opcionales contengan la misma cantidad de elementos.

Por lo tanto, me tomé la libertad de implementar cosas de modo que [NULL]se proporcionen dondequiera que *falten elementos separados debido a que las listas tienen diferentes longitudes o los argumentos se *especifican vacíos.

\documentclass{article}
\usepackage{xparse}

\makeatletter
%%=============================================================================
%% Little helpers:
%%.............................................................................
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% 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>}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\z@\@secondoftwo}%
  {\expandafter\z@\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%%   \romannumeral\UD@ExtractFirstArgLoop{<argument>\UD@SelDOm}%
%%   yields <argument>'s 1st undelimited argument.
%%   <argument> must not be blank, i.e., must neither be empty nor consist
%%   only of explicit character tokens of catcode 10 and charcode 32.
%%
%%   \UD@SelDOm must not be defined in terms of \outer !
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%


%%=============================================================================
%% \mxm starts a loop for collecting an arbitrary amount of optional arguments.
%%.............................................................................
\NewDocumentCommand\mxm{}{\innermxm{}}%
%%-----------------------------------------------------------------------------
%% \innermxm checks if another optional argument is present.
%% If so it will be collected and \innermxm is called again.
%% Otherwise the loop for forming the calls to \x is started.
%%.............................................................................
\NewDocumentCommand\innermxm{m >{\SplitList{*}}o}{%
  % #1 - list of brace-nested optional arguments collected so far.
  % #2 - either the no-value-marker or the next optional argument:
  \IfNoValueTF{#2}{%
    % Start the loop for forming the calls to \x/for re-arranging things:
    %   \romannumeral is not really needed here, but while writing
    %   this I wanted the missing-number-error in case of messing up
    %   the tail-recursive \mxmloop's  flipping-around/exchanging
    %   of arguments. ;-)
    \romannumeral\mxmloop{\x}{}{}{#1}{}%
  }{%
    % Add the current optional argument to the list #1 and check if
    % another optional argument is present...
    \innermxm{#1{#2}}%
  }%
}%

\newcommand\mxmloop[5]{%
  %#1 - token-list produced so far forming current new call to \x
  %#2 - new list of lists
  %#3 - indicator if all elements of current list of lists were empty. 
  %#4 - current list of lists
  %#5 - list of calls to \x
  \UD@CheckWhetherNull{#4}{%
    \UD@CheckWhetherNull{#3}{%
      \z@#5% <- this \z@ terminates the (actually not needed)
           %   \romannumeral-expansion started by \innermxm. 
           %   It denotes a non-positive number and therefore
           %   gets removed silently.
    }{%
      \mxmloop{\x}{}{}{#2}{#5#1}%
    }%
  }{%
    \UD@PassFirstToSecond{#5}{%
      \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#4}{%
        \expandafter\UD@CheckWhetherNull\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}}{%
          \UD@PassFirstToSecond{#3}{%
            \UD@PassFirstToSecond{#2{}}{%
              \UD@PassFirstToSecond{#1[NULL]}{\mxmloop}%
            }%
          }%
        }{%
          \UD@PassFirstToSecond{m}{%
            \expandafter\UD@PassFirstToSecond\expandafter{%
              \romannumeral
              \expandafter\expandafter\expandafter\UD@PassFirstToSecond
              \expandafter\expandafter\expandafter{%
              \expandafter\@firstoftwo\expandafter{\expandafter}%
              \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}}{\z@#2}%
            }{%
              \expandafter\UD@CheckWhetherNull\expandafter{%
                \romannumeral\expandafter
                \UD@ExtractFirstArgLoop\expandafter{%
                  \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}%
                \UD@SelDOm}%
              }{%
                \UD@PassFirstToSecond{#1[NULL]}{\mxmloop}%
              }{%
                \expandafter\UD@PassFirstToSecond\expandafter{%
                  \romannumeral
                  \expandafter\UD@Exchange\expandafter{%
                    \romannumeral\expandafter
                    \UD@ExtractFirstArgLoop\expandafter{%
                      \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}%
                    \UD@SelDOm}%
                  }{\z@#1}%
                }{\mxmloop}%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}%

%%=============================================================================
% Let's define \x to collect an arbitrary amount of optional arguments and to display them:
\NewDocumentCommand\x{}{\innerx{}}%
\NewDocumentCommand\innerx{mo}{%
  \IfNoValueTF{#2}{\par\noindent\texttt{\detokenize\expandafter{\string\x#1}}}{\innerx{#1[#2]}}%
}%
\makeatother

\begin{document}

\footnotesize

\noindent Test 1:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
   [ [3,5]*[ 6,-7]*[-8, 9] ]

\bigskip\hrule\bigskip

\noindent Test 2:

\mxm
   [ [3,2]*[-3, 0] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
   [ [3,5]*[ 6,-7]*[-8, 9] ]

\bigskip\hrule\bigskip

\noindent Test 3:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
   [ [1,1]*[ 0,-2]* * ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 4:

\mxm
   [ [1,1]*[ 0,-2]]
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8]*[17,4] ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 5:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
   [ ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 6:

\mxm
   [ [3,2]*[-3, 0] ]
   [ [1,1]*[ 0,-2] ]
   [ [3,5]*[ 6,-7] ]
   [ [2,7]*[ 7,-0] ]
   [ [8,4]*[ 6,-0] ]

\bigskip\hrule\bigskip

\noindent Test 7:

\mxm
   [ [3,2]*[-3, 0]*[1,1]*[ 0,-2]*[3,5]*[ 6,-7] ]

\bigskip\hrule\bigskip

\noindent Test 8:

\mxm
   [ [3,2] ]

\bigskip\hrule\bigskip

\noindent Test 9:

\mxm
   [  ]

\bigskip\hrule\bigskip

\noindent Test 10:

\mxm

\noindent bla

\end{document}

ingrese la descripción de la imagen aquí



Se puede utilizar una variación de esto para crear matrices:

\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath}

\makeatletter
%%=============================================================================
%% Little helpers:
%%.............................................................................
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% 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>}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\z@\@secondoftwo}%
  {\expandafter\z@\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%%   \romannumeral\UD@ExtractFirstArgLoop{<argument>\UD@SelDOm}%
%%   yields <argument>'s 1st undlimited argument.
%%   <argument> must not be blank, i.e., must neither be empty nor consist
%%   only of explicit character tokens of catcode 10 and charcode 32.
%%
%%   \UD@SelDOm must not be defined in terms of \outer !
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%


%%=============================================================================
%% \mxm starts a loop for collecting an arbitrary amount of optional arguments.
%%.............................................................................
\NewDocumentCommand\mxm{s}{%
  \IfBooleanTF{#1}{\innermxm{\x*}{}}{\innermxm{\x}{}}%
}%
%%-----------------------------------------------------------------------------
%% \innermxm checks if another optional argument is present.
%% If so it will be collected and \innermxm is called again.
%% Otherwise the loop for forming the calls to \x is started.
%%.............................................................................
\NewDocumentCommand\innermxm{mm >{\SplitList{*}}o}{%
  % #1 - command for creating matrices
  % #2 - list of brace-nested optional arguments collected so far.
  % #3 - either the no-value-marker or the next optional argument:
  \IfNoValueTF{#3}{%
    % Start the loop for forming the calls to \x/for re-arranging things:
    %   \romannumeral is not really needed here, but while writing
    %   this I wanted the missing-number-error in case of messing up
    %   the tail-recursive \mxmloop's  flipping-around/exchanging
    %   of arguments. ;-)
    \romannumeral\mxmloop{#1}{}{}{}{#2}{}%
  }{%
    % Add the current optional argument to the list #2 and check if
    % another optional argument is present...
    \innermxm{#1}{#2{#3}}%
  }%
}%

\newcommand\mxmloop[6]{%
  %#1 - command for creating matrices
  %#2 - token-list produced so far forming current command for creating matrices
  %#3 - new list of lists
  %#4 - indicator if all elements of current list of lists were empty. 
  %#5 - current list of lists
  %#6 - list of calls for creating matrices
  \UD@CheckWhetherNull{#5}{%
    \UD@CheckWhetherNull{#4}{%
      \z@#6% <- this \z@ terminates the (actually not needed)
           %   \romannumeral-expansion started by \innermxm. 
           %   It denotes a non-positive number and therefore
           %   gets removed silently.
    }{%
      \mxmloop{#1}{}{}{}{#3}{#6#1#2}%
    }%
  }{%
    \UD@PassFirstToSecond{#6}{%
      \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#5}{%
        \expandafter\UD@CheckWhetherNull\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}}{%
          \UD@PassFirstToSecond{#4}{%
            \UD@PassFirstToSecond{#3{}}{%
              \UD@PassFirstToSecond{#2%[NULL]
                                      }{\mxmloop{#1}}%
            }%
          }%
        }{%
          \UD@PassFirstToSecond{m}{%
            \expandafter\UD@PassFirstToSecond\expandafter{%
              \romannumeral
              \expandafter\expandafter\expandafter\UD@PassFirstToSecond
              \expandafter\expandafter\expandafter{%
              \expandafter\@firstoftwo\expandafter{\expandafter}%
              \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}}{\z@#3}%
            }{%
              \expandafter\UD@CheckWhetherNull\expandafter{%
                \romannumeral\expandafter
                \UD@ExtractFirstArgLoop\expandafter{%
                  \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}%
                \UD@SelDOm}%
              }{%
                \UD@PassFirstToSecond{#2%[NULL]
                                        }{\mxmloop{#1}}%
              }{%
                \expandafter\UD@PassFirstToSecond\expandafter{%
                  \romannumeral
                  \expandafter\UD@Exchange\expandafter{%
                    \romannumeral\expandafter
                    \UD@ExtractFirstArgLoop\expandafter{%
                      \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}%
                    \UD@SelDOm}%
                  }{\z@#2}%
                }{\mxmloop{#1}}%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}%

%%=============================================================================
% Let's define \x to collect an arbitrary amount of optional arguments and to create a matrix of them:
\NewDocumentCommand\x{s}{%
  \IfBooleanTF{#1}{\innerx{}{}{pmatrix}}{\innerx{}{}{bmatrix}}%
}%
\NewDocumentCommand\innerx{mmm >{\SplitList{,}}o}{%
  % #1 - matrix-content created so far
  % #2 - things to prepend to matrix-row to create (empty with 1st row, \\ otherwise)
  % #3 - name of matrix-environment
  % #4 - optional argument from which next matrix-row is to be created
  \IfNoValueTF{#4}%
  {\UD@CheckWhetherNull{#1}{}{\begin{#3}#1\end{#3}}}%
  {%
    \expandafter\innerx
    \expandafter{\romannumeral\expandafter\UD@Exchange\expandafter{\romannumeral\intersperseloop{#4}{}{}}{\z@#1#2}}%
    {\\}%
    {#3}%
  }%
}%
\newcommand\intersperseloop[3]{%
  %#1 - argument list
  %#2 - interspersed list
  %#3 - token to prepend (empty with 1st element, & otherwise)
  \UD@CheckWhetherNull{#1}{\z@#2}{%
    \UD@PassFirstToSecond{&}{%
      \expandafter\UD@PassFirstToSecond\expandafter{%
        \romannumeral\expandafter\UD@Exchange\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#1\UD@SelDOm}}{\z@#2#3}%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#1}{%
          \intersperseloop
        }%
      }%
    }%
  }%
}%

\makeatother

\begin{document}

\footnotesize

\noindent Test 1:

$$\mxm
     [ [3,2]*[-3, 0]*[ 1,-2] ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$

\bigskip\hrule\bigskip

\noindent Test 2:

$$\mxm*
     [ [3,2]*[-3, 0]         ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$

\bigskip\hrule\bigskip

\noindent Test 2a:

$$\mxm
     [ [3,2]*       *[-3, 0] ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$



\bigskip\hrule\bigskip

\noindent Test 3:

$$\mxm
     [ [3,2] * [-3, 0] * [ 1,-2] * [2,8] ]
     [ [1,1] * [ 0,-2] *         *       ]
     [ [3,5] * [ 6,-7] * [-8, 9] *       ]$$

\bigskip\hrule\bigskip

\noindent Test 4:

$$\mxm
     [ [1,1]*[ 0,-2]]
     [ [3,2]*[-3, 0]*[ 1,-2]*[2,8]*[17,4] ]
     [ [3,5]*[ 6,-7]*[-8, 9]* ]$$

\bigskip\hrule\bigskip

\noindent Test 5:

$$\mxm
     [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
     [ ]
     [ [3,5]*[ 6,-7]*[-8, 9]* ]$$

\bigskip\hrule\bigskip

\noindent Test 6:

$$\mxm*
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]$$

\bigskip\hrule\bigskip

\noindent Test 6b:

$$\mxm
     [ [3,2] * [-3, 0]   *         ]
     [ [1,1] *           * [ 0,-2] ]
     [ [3,5] *           * [ 6,-7] ]
     [ [2,7] *           * [ 7,-0] ]
     [ [8,4] *           * [ 6,-0] ]
     [       *           * [ 6,-0] ]$$


\bigskip\hrule\bigskip

\noindent Test 7:

$$\mxm
     [ [3,2]*[-3, 0]*[1,1]*[ 0,-2]*[3,5]*[ 6,-7] ]$$

\bigskip\hrule\bigskip

\noindent Test 8:

$$\mxm
     [ [3,2] ]$$

\bigskip\hrule\bigskip

\noindent Test 9:

$$\mxm
     [  ]$$

\bigskip\hrule\bigskip

\noindent Test 10:

$$\mxm$$

\noindent bla

\end{document}

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Respuesta2

Si desea crear un \mxm:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]

hacer

\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]

entonces puedes definir

\def\mxm [ [#1]*[#2]*[#3] ] [ [#4]*[#5]*[#6] ]{%
   \x[#1][#4]
   \x[#2][#5]
   \x[#3][#6]
}

Editar:Si entiendo su demanda, entonces necesita transponer los parámetros. Cuando \mxmse proporciona con filas y columnas arbitrarias, entonces es necesario convertir el

\mxm
   [ [A1]*[A2]*[A3]*[A4] ]
   [ [B1]*[B2]*[B3]*[B4] ]
   [ [C1]*[C2]*[C3]*[C4] ]

en una serie de llamadas:

\x[A1][B1][C1]
\x[A2][B2][C2]
\x[A3][B3][C3]
\x[A4][B4][C4]

Puedes probar el siguiente código:

\newcount\numrows \newcount\tmpnum
\def\mxm {\numrows=0 \mxmA}
\def\mxmA [ #1 ] {\advance\numrows by1 \sdef{r:\the\numrows}{#1}%
   \futurelet\next\mxmB}
\def\mxmB {\ifx\next[\expandafter\mxmA \else \expandafter \mxmC\fi}
\def\mxmC {\expandafter\ifx \csname r:1\endcsname \empty \else
   \tmpnum=0 \def\xparams{}%
   \loop
      \advance\tmpnum by1
      \expandafter \expandafter \expandafter \mxmD
           \csname r:\the\tmpnum\endcsname \end
      \ifnum\tmpnum<\numrows \repeat
   \expandafter \x \xparams \relax
   \expandafter \mxmC \fi
}
\def\mxmD #1[#2]#3\end{\sdef{r:\the\tmpnum}{#3}\addto\xparams{[#2]}}

\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\sdef#1{\expandafter\def\csname#1\endcsname}

% Just for testing:
\def\x #1\relax{\message{running \string\x #1}}

\mxm
     [ [A1]*[A2]*[A3]*[A4] ]
     [ [B1]*[B2]*[B3]*[B4] ]
     [ [C1]*[C2]*[C3]*[C4] ]

\bye

El resultado del mensaje de este código (después de \pdftex testfile) es:

running \x[A1][B1][C1] running \x[A2][B2][C2]
running \x[A3][B3][C3] running \x[A4][B4][C4]

Respuesta3

No creo que éste sea un buen enfoque, particularmente en los ocho argumentos opcionales. Pero el cliente siempre tiene la razón.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand\makematrix{ s o o o o o o o o }
 {
  \begin{ \IfBooleanTF { #1 } { p } { b } matrix }
  \bryce_make_matrix:nnnnnnnn { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
  \end{ \IfBooleanTF { #1 } { p } { b } matrix }
 }
\NewDocumentCommand{\mxm} { s o o o o o o o o }
 {
  \group_begin: % localize the setting of the sequences
  \IfValueT{#2}
   {
    \seq_set_split:Nnn \l__bryce_mxm_i_seq { * } { #2 }
   }
  \IfValueT{#3}
   {
    \seq_set_split:Nnn \l__bryce_mxm_ii_seq { * } { #3 }
   }
  \IfValueT{#4}
   {
    \seq_set_split:Nnn \l__bryce_mxm_iii_seq { * } { #4 }
   }
  \IfValueT{#5}
   {
    \seq_set_split:Nnn \l__bryce_mxm_iv_seq { * } { #5 }
   }
  \IfValueT{#6}
   {
    \seq_set_split:Nnn \l__bryce_mxm_v_seq { * } { #6 }
   }
  \IfValueT{#7}
   {
    \seq_set_split:Nnn \l__bryce_mxm_vi_seq { * } { #7 }
   }
  \IfValueT{#8}
   {
    \seq_set_split:Nnn \l__bryce_mxm_vii_seq { * } { #8 }
   }
  \IfValueT{#9}
   {
    \seq_set_split:Nnn \l__bryce_mxm_viii_seq { * } { #9 }
   }
  \cs_set_protected:Nx \__bryce_mxm:
   {
    \makematrix \IfBooleanT { #1 } { * }
   }
  \__bryce_mxm_do:
  \group_end:
 }

\cs_new_protected:Nn \bryce_make_matrix:nnnnnnnn
 {
  \tl_if_novalue:nF { #1 } { \__bryce_make_row:n { #1 } }
  \tl_if_novalue:nF { #2 } { \__bryce_make_row:n { #2 } }
  \tl_if_novalue:nF { #3 } { \__bryce_make_row:n { #3 } }
  \tl_if_novalue:nF { #4 } { \__bryce_make_row:n { #4 } }
  \tl_if_novalue:nF { #5 } { \__bryce_make_row:n { #5 } }
  \tl_if_novalue:nF { #6 } { \__bryce_make_row:n { #6 } }
  \tl_if_novalue:nF { #7 } { \__bryce_make_row:n { #7 } }
  \tl_if_novalue:nF { #8 } { \__bryce_make_row:n { #8 } }
 }

\cs_new_protected:Nn \__bryce_make_row:n
 {
  \clist_set:Nn \l__bryce_row_clist { #1 }
  \clist_use:Nn \l__bryce_row_clist { & }
  \\
 }


\seq_new:N \l__bryce_mxm_i_seq
\seq_new:N \l__bryce_mxm_ii_seq
\seq_new:N \l__bryce_mxm_iii_seq
\seq_new:N \l__bryce_mxm_iv_seq
\seq_new:N \l__bryce_mxm_v_seq
\seq_new:N \l__bryce_mxm_vi_seq
\seq_new:N \l__bryce_mxm_vii_seq
\seq_new:N \l__bryce_mxm_viii_seq
\int_new:N \l__bryce_mxm_int

\cs_new_protected:Nn \__bryce_mxm_do:
 {
  \int_step_inline:nn { \seq_count:N \l__bryce_mxm_i_seq }
   {
    \int_set:Nn \l__bryce_mxm_int { ##1 }
    \exp_last_unbraced:Ne \__bryce_mxm: \__bryce_mxm_args:
   }
 }
\cs_new:Nn \__bryce_mxm_args:
 {
  \int_step_function:nN { 8 } \__bryce_mxm_args_aux:n
 }
\cs_new:Nn \__bryce_mxm_args_aux:n
 {
  \seq_item:cn { l__bryce_mxm_\int_to_roman:n { #1 }_seq } { \l__bryce_mxm_int }
 }

\ExplSyntaxOff

\begin{document}

\[
\makematrix[3,2][1,1]
\makematrix[-3, 0][ 0,-2]
\makematrix[ 1,-2][-1, 3]
\]

\[
\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
\]

\[
\makematrix*[3,2][1,1]
\makematrix*[-3, 0][ 0,-2]
\makematrix*[ 1,-2][-1, 3]
\]

\[
\mxm*
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
\]

\end{document}

ingrese la descripción de la imagen aquí

Respuesta4

Las cosas serían mucho más fáciles si no te importara usar aparatos ortopédicos.

ingrese la descripción de la imagen aquí

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

\tl_new:N \l_doc_tmpa_tl
\tl_new:N \l_doc_tmpb_tl
\tl_new:N \l_doc_tmpc_tl

\int_new:N \l_doc_tmpa_int
\int_new:N \l_doc_tmpb_int
\int_new:N \l_doc_tmpc_int
\clist_new:N \l_doc_tmpa_clist

\seq_new:N \l_doc_tmpa_seq
\seq_new:N \l_doc_tmpb_seq
\seq_new:N \l_doc_tmpc_seq
\seq_new:N \l_doc_tmpd_seq
\seq_new:N \l_doc_tmpe_seq

\cs_set:Npn \doc_extract_square_bracket:nN #1#2 {
  \tl_set:Nn \l_doc_tmpa_tl {#1}
  \seq_clear:N #2
  \int_set:Nn \l_doc_tmpa_int {0}
  \tl_clear:N \l_doc_tmpc_tl
  
  \bool_do_until:nn {\tl_if_empty_p:N \l_doc_tmpa_tl} {
    \tl_set:Nx \l_doc_tmpb_tl {\tl_head:N \l_doc_tmpa_tl}
    \tl_set:Nx \l_doc_tmpa_tl {\tl_tail:N \l_doc_tmpa_tl}
    
    \exp_args:NV \str_case:nnF \l_doc_tmpb_tl {
      {[} {
        \int_compare:nNnT {\l_doc_tmpa_int} > {0} {
          \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
        }
        \int_incr:N \l_doc_tmpa_int
      }
      {]} {
        \int_decr:N \l_doc_tmpa_int
        \int_compare:nNnTF {\l_doc_tmpa_int} > {0} {
          \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
        }{
          \seq_put_right:NV #2 \l_doc_tmpc_tl
          \tl_clear:N \l_doc_tmpc_tl
        }
      }
    } {
      \int_compare:nNnT {\l_doc_tmpa_int} > {0} {
        \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
      }
    }
  }
}

\newcommand{\x}[1]{
  \seq_clear:N \l_doc_tmpc_seq
  \doc_extract_square_bracket:nN {#1} \l_doc_tmpb_seq
  \seq_map_variable:NNn \l_doc_tmpb_seq \l_doc_tmpa_tl {
    \clist_set:NV \l_doc_tmpa_clist \l_doc_tmpa_tl
    \seq_put_right:Nx \l_doc_tmpc_seq {\clist_use:Nn \l_doc_tmpa_clist {\c_alignment_token}}
  }
  \begin{bmatrix}
    \seq_use:Nn \l_doc_tmpc_seq {\\}
  \end{bmatrix}
}

\cs_set:Npn \doc_temp_seq_name:n #1 {
  l__doc_mat_\int_to_alph:n {#1}_seq
}

\newcommand{\mxm}[1]{
  \doc_extract_square_bracket:nN {#1} \l_doc_tmpd_seq
  
  \seq_get_left:NN \l_doc_tmpd_seq \l_doc_tmpa_tl
  \exp_args:NV \doc_extract_square_bracket:nN \l_doc_tmpa_tl \l_doc_tmpe_seq
  \int_set:Nn \l_doc_tmpb_int {\seq_count:N \l_doc_tmpe_seq}
  \seq_show:N \l_doc_tmpd_seq
  \int_step_inline:nn {\l_doc_tmpb_int} {
    \seq_clear:c {\doc_temp_seq_name:n {##1}}
  }
  
  \seq_map_variable:NNn \l_doc_tmpd_seq \l_doc_tmpa_tl {
    \exp_args:NV \doc_extract_square_bracket:nN \l_doc_tmpa_tl \l_doc_tmpe_seq
    \int_set:Nn \l_doc_tmpc_int {1}
    \seq_map_variable:NNn \l_doc_tmpe_seq \l_doc_tmpb_tl {
      \tl_clear:N \l_doc_tmpc_tl
      \tl_put_right:Nn \l_doc_tmpc_tl {[}
      \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
      \tl_put_right:Nn \l_doc_tmpc_tl {]}
      \seq_put_right:cV {\doc_temp_seq_name:n {\l_doc_tmpc_int}} \l_doc_tmpc_tl
      \int_incr:N \l_doc_tmpc_int
    }
  }
  
  \int_step_inline:nn {\l_doc_tmpb_int} {
    \tl_set:Nx \l_doc_tmpa_tl {\exp_not:N\x{\seq_use:cn {\doc_temp_seq_name:n {##1}} {}}}
    \tl_use:N \l_doc_tmpa_tl
  }
}

\ExplSyntaxOff

\begin{document}
$$\x{[1,2,3][4,5,6][7,8,9]}$$
$$\x{[1,2,3,4,5,6][a,b,c,d,e,f][6,5,4,3,2,1]}$$
$$\x{[1,2][3,4][5,6][7,8][9,10][11,12]}$$
$$
\mxm{
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
}
$$
$$
\mxm{
   [ [3,2]+[-3, 0]+[ 1,-2] ]
   [ [1,1]+[ 0,-2]+[-1, 3] ]
}
$$
$$
\mxm{
   [ [3,2][-3, \alpha][ 1,-2][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][\frac{3}{2}, 3][5,6] ]
}
$$
\end{document}

información relacionada