Macro que evalúa el número de argumentos sin limitación.

Macro que evalúa el número de argumentos sin limitación.

¿Es posible tener una macro como esta?

\documentclass{article}
\usepackage{xparse}
\pagestyle{empty}
\ExplSyntaxOn
\NewDocumentCommand{\HowManyArguments}{ oooooooo }
    {
        \IfNoValueTF {#1} { 0 }{
            \IfNoValueTF {#2} { 1 }{
                \IfNoValueTF {#3}  { 2 }{
                     \IfNoValueTF {#4}  { 3 }{
                          \IfNoValueTF {#5}  { 4 }{
                               \IfNoValueTF {#6}  { 5 }{
                                    \IfNoValueTF {#7}  { 6 }{
                                         \IfNoValueTF {#8}  { 7 }{ So many }
                                    }
                               }
                          }
                     }
                }
            }
        }
    }
\ExplSyntaxOff
\begin{document}

The amount of arguments in this macro is \HowManyArguments[Cake][Chair][Stool][Bicycle] .

\end{document}

Excepto uno que no tiene limitaciones, un poco como el \powertowerhilo, donde el resultado está incrustado en el resto cada vez:¿Cómo puedo componer una potencia diez veces mayor (una torre de poderes) con LaTeX?

La idea entonces es utilizar el primer argumento de la macro para definir el número de argumentos.

La razón por la que necesito el enfoque "powertower" es por la parte 2: quiero rotar entre colores según el número del argumento.

Intenta compilar esto:

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\pagestyle{empty}
\ExplSyntaxOn
\NewDocumentCommand{\HowManyArguments}{ oooooooo }
    {
        \IfNoValueTF {#1} {}{
            \IfNoValueTF {#2} {\textcolor{blue}{#1(}...\textcolor{blue}{)}}{
                \IfNoValueTF {#3}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}...\textcolor{green}{)}\textcolor{blue}{)}}{
                     \IfNoValueTF {#4}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}...\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}{
                          \IfNoValueTF {#5}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}\textcolor{blue}{#4(}...\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}{
                               \IfNoValueTF {#6}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}\textcolor{blue}{#4(}\textcolor{green}{#5(}...\textcolor{green}{)}\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}{
                                    \IfNoValueTF {#7}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}\textcolor{blue}{#4(}\textcolor{green}{#5(}\textcolor{red}{#6(}...\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}{
                                         \IfNoValueTF {#8}  {\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}\textcolor{blue}{#4(}\textcolor{green}{#5(}\textcolor{red}{#6(}\textcolor{blue}{#7(}...\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}{\textcolor{blue}{#1(}\textcolor{green}{#2(}\textcolor{red}{#3(}\textcolor{blue}{#4(}\textcolor{green}{#5(}\textcolor{red}{#6(}\textcolor{blue}{#7(}\textcolor{green}{#8(}...\textcolor{green}{)}\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}\textcolor{red}{)}\textcolor{green}{)}\textcolor{blue}{)}}
                                    }
                               }
                          }
                     }
                }
            }
        }
    }
\ExplSyntaxOff
\begin{document}

Try this one instead: \HowManyArguments[Mandatory][Argument][What][Have][You][Done]

\end{document}

Esta es la idea completa de lo que estoy intentando construir, pero sin limitaciones.

Respuesta1

Sería más coherente con el diseño de LaTeX utilizar una lista separada por comas:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

\documentclass{article}

\makeatletter
\newcommand\HowManyArguments[1]{{%
\count@\z@
\@for\tmp:=#1\do{\advance\count@\@ne}%
There are \the\count@\ arguments\par
\@for\tmp:=#1\do{(\tmp}%
\@for\tmp:=#1\do{)}}}
\makeatother


\begin{document}

\HowManyArguments{Lots,of,arguments,in,this,thread}

\end{document}

O con color

\documentclass{article}

\usepackage{color}
\makeatletter
\newcommand\HowManyArguments[1]{{%
\count@\z@
\@for\tmp:=#1\do{\advance\count@\@ne}%
There are \the\count@\ arguments\par
\@tempcnta\z@
\@for\tmp:=#1\do{%
\advance\@tempcnta\@ne
\textcolor[RGB]{\the\numexpr255*\@tempcnta/(\count@)\relax,
                 0,
                 \the\numexpr255-(255*\@tempcnta/(\count@))\relax}%
                {\tmp(}}%
\@tempcnta\count@
\@for\tmp:=#1\do{%
\textcolor[RGB]{\the\numexpr255*\@tempcnta/(\count@)\relax,
                 0,
                 \the\numexpr255-(255*\@tempcnta/(\count@))\relax}%
                {)}%
\advance\@tempcnta\m@ne
}}}
\makeatother


\begin{document}

\HowManyArguments{Lots,of,arguments,in,this,thread}

\end{document}

Respuesta2

Una expl3solución (solo para complacer a David). Hago el cálculo sólo una vez, llenando dos listas de tokens y entregándolas.

\documentclass{article}
\usepackage{xparse,xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\HMA}{m}
 {
  \leavevmode
  \group_begin:
  \hma_process_args:n { #1 }
  \group_end:
 }

\seq_new:N \l__hma_args_seq
\tl_new:N \l__hma_opening_tl
\tl_new:N \l__hma_closing_tl
\int_new:N \l__hma_step_int
\int_new:N \l__hma_args_int

\cs_new_protected:Npn \hma_process_args:n #1
 {
  \seq_set_split:Nnn \l__hma_args_seq { , } { #1 }
  \tl_clear:N \l__hma_opening_tl
  \tl_set:Nn \l__hma_closing_tl { \dots }
  \int_zero:N \l__hma_step_int
  \int_set:Nn \l__hma_args_int { \seq_count:N \l__hma_args_seq }
  \color[RGB]{0,0,255}
  \seq_map_inline:Nn \l__hma_args_seq
   {
    \int_incr:N \l__hma_step_int
    \tl_put_right:Nx \l__hma_opening_tl
     {
      \exp_not:n { ##1 ( }
      \group_begin:
      \exp_not:N \color[RGB] { \__hma_set_color: }
     }
    \tl_put_right:Nn \l__hma_closing_tl { \group_end: ) }
   }
  \tl_use:N \l__hma_opening_tl \tl_use:N \l__hma_closing_tl
 }

\cs_new:Npn \__hma_set_color:
 {
  \int_eval:n { 255 * \l__hma_step_int / \l__hma_args_int },
  0,
  \int_eval:n { 255 - ( 255 * \l__hma_step_int / \l__hma_args_int ) }
 }

\ExplSyntaxOff

\begin{document}

\HMA{Lots,of,arguments,in,this,thread}

\end{document}

ingrese la descripción de la imagen aquí

Simplemente cambiar una línea permite evitar los puntos y usar el último elemento para los paréntesis más internos.

\documentclass{article}
\usepackage{xparse,xcolor}

\ExplSyntaxOn
\NewDocumentCommand{\HMA}{m}
 {
  \leavevmode
  \group_begin:
  \hma_process_args:n { #1 }
  \group_end:
 }

\seq_new:N \l__hma_args_seq
\tl_new:N \l__hma_opening_tl
\tl_new:N \l__hma_closing_tl
\int_new:N \l__hma_step_int
\int_new:N \l__hma_args_int

\cs_new_protected:Npn \hma_process_args:n #1
 {
  \seq_set_split:Nnn \l__hma_args_seq { , } { #1 }
  \tl_clear:N \l__hma_opening_tl
  \seq_pop_right:NN \l__hma_args_seq \l__hma_closing_tl % <---- CHANGE
  \int_zero:N \l__hma_step_int
  \int_set:Nn \l__hma_args_int { \seq_count:N \l__hma_args_seq }
  \color[RGB]{0,0,255}
  \seq_map_inline:Nn \l__hma_args_seq
   {
    \int_incr:N \l__hma_step_int
    \tl_put_right:Nx \l__hma_opening_tl
     {
      \exp_not:n { ##1 ( }
      \group_begin:
      \exp_not:N \color[RGB] { \__hma_set_color: }
     }
    \tl_put_right:Nn \l__hma_closing_tl { \group_end: ) }
   }
  \tl_use:N \l__hma_opening_tl \tl_use:N \l__hma_closing_tl
 }

\cs_new:Npn \__hma_set_color:
 {
  \int_eval:n { 255 * \l__hma_step_int / \l__hma_args_int },
  0,
  \int_eval:n { 255 - ( 255 * \l__hma_step_int / \l__hma_args_int ) }
 }

\ExplSyntaxOff

\begin{document}

\HMA{Lots,of,arguments,in,this,thread}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta3

Para abordar el deseo del OP de algo como Lots(of(arguments(in(this(thread))))), creé la macro \groupargs{{}{}{}{}}y doy un ejemplo.

Si bien cambio los colores discretamente módulo del nivel de anidamiento (como se hace en el MWE del OP), se podría insertar cualquier algoritmo para calcular el color en función del nivel de anidamiento.

\documentclass{article}
\usepackage{readarray}
\usepackage{xcolor}
\newcounter{argindex}
\newcounter{colindex}
\def\groupargs#1{\def\lparen{}\def\rparen{}\getargsC{#1}%
  \setcounter{argindex}{0}\setcounter{colindex}{0}\nextarg}
\def\nextarg{\stepcounter{argindex}\stepcounter{colindex}%
  \ifnum\theargindex>\narg\else\lparen%
  \ifnum\thecolindex=1\def\mycolor{blue}\else%
    \ifnum\thecolindex=2\def\mycolor{green}\else%
      \ifnum\thecolindex=3\def\mycolor{red}\setcounter{colindex}{0}%
  \fi\fi\fi%
  \def\lparen{(}%
  \textcolor{\mycolor}{\csname arg\romannumeral\theargindex\endcsname%
  {\def\rparen{)}\nextarg}}\rparen\fi%
}
\begin{document}
\groupargs{Mandatory Argument What Have {You Indeed} Done ...}
\end{document}

ingrese la descripción de la imagen aquí

información relacionada