Cómo definir una macro que toma la definición de una macro como argumento

Cómo definir una macro que toma la definición de una macro como argumento

Nos gustaría definir una macro \ellipsisque tome cuatro argumentos y tenga el siguiente comportamiento:

\ellipsis{x^{#DUMMY#}}{0}{5}{+}

y salidas:

ingrese la descripción de la imagen aquí

la cadena del patrón #DUMMY#(que no tiene que ser exactamente esta cadena) debe reemplazarse por el segundo y tercer argumento. Entonces, el primer argumento es la definición de una macro en sí misma.


Hemos probado un par de cosas pero siempre terminamos usando dos macros diferentes para obtener el comportamiento deseado. Por ejemplo haciendo

\newcommand{\ellipMacro}[1]{x^{#1}}
\newcommand{\ellip}[4]{\csuse{#1}{#2}#4\ldots #4 \csuse{#1}{#3}}

Esto utiliza la secuencia de control \csusedel paquete.caja de herramientas(Estamos bien con el uso de cualquier paquete).

Nos gustaría hacer esto en sólounocomando, por lo tanto, la definición de la macro interna ( x^{#DUMMY}) debe colocarse dentro de la definición de la macro más grande.

Incluya cualquier idea que pueda tener sobre cómo hacer esto.

Respuesta1

Esta es una adaptación de mi respuesta en¿Cómo crear un comando para automatizar la creación de productos similares a la factorización prima?

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

\ExplSyntaxOn
\NewDocumentCommand{\elliptic}{O{i}mmmm}
 {% #1 = item to substitute
  % #2 = main term
  % #3 = first index
  % #4 = last index
  % #5 = operation
  \group_begin:
  \lucas_elliptic:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 }
  \group_end:
 }
\tl_new:N \l__lucas_elliptic_term_tl
\cs_generate_variant:Nn \cs_set:Nn { NV }
\cs_new:Nn \lucas_elliptic:nnnnn
 {
  \tl_set:Nn \l__lucas_elliptic_term_tl { #2 }
  \regex_replace_all:nnN
   { #1 } % search
   { \cB\{\cP\#1\cE\} } % replace
   \l__lucas_elliptic_term_tl % what to act on
  \cs_set:NV \__lucas_elliptic_term:n \l__lucas_elliptic_term_tl
  \__lucas_elliptic_term:n { #3 }
  #5 \dots #5
  \__lucas_elliptic_term:n { #4 }
 }
\ExplSyntaxOff

\begin{document}

$\elliptic{x^{i}}{0}{5}{+}$

$\elliptic{x_{i}}{0}{5}{+}$

$\elliptic[k]{(x_{k}+y_{k}i)}{1}{n}{}$

\end{document}

ingrese la descripción de la imagen aquí

Si está dispuesto a utilizarlo #1como marcador de posición, esto se puede simplificar:

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

\ExplSyntaxOn
\NewDocumentCommand{\elliptic}{mmmm}
 {% #1 = main term
  % #2 = first index
  % #3 = last index
  % #4 = operation
  \group_begin:
  \lucas_elliptic:nnnn { #1 } { #2 } { #3 } { #4 }
  \group_end:
 }
\cs_new:Nn \lucas_elliptic:nnnn
 {
  \cs_set:Nn \__lucas_elliptic_term:n { #1 }
  \__lucas_elliptic_term:n { #2 }
  #4 \dots #4
  \__lucas_elliptic_term:n { #3 }
 }
\ExplSyntaxOff

\begin{document}

$\elliptic{x^{#1}}{0}{5}{+}$

$\elliptic{x_{#1}}{0}{5}{+}$

$\elliptic{(x_{#1}+y_{#1}i)}{1}{n}{}$

\end{document}

Respuesta2

ingrese la descripción de la imagen aquí

Para el ejemplo dado donde el argumento viene al final del marcador de posición, no es necesario definir ningún comando interno, pero para el caso general el formulario \ellipsisbtoma como primer argumento el cuerpo de cualquier definición de comando de un argumento. Esto permite la forma 0^2...5^2 que se muestra al final.

\documentclass{article}



\begin{document}

\newcommand\ellipsis[4]{#1{#2}#4\cdots#4#1{#3}}

$\ellipsis{x^}{0}{5}{+}$

\newcommand\ellipsisb[4]{%
\def\tmp##1{#1}\tmp{#2}#4\cdots#4\tmp{#3}}

$\ellipsisb{x^{#1}}{0}{5}{+}$

$\ellipsisb{{#1}^2}{0}{5}{+}$



\end{document}

Respuesta3

Quizás no entiendo lo que quieres, pero hasta donde puedo ver, no lo necesitas \csuseaquí y puedes definir:

\newcommand\ellip[4]{{#1}^{#3}#2\dots#2{#1}^{#4}}

De esta manera $\ellip x+04$ y $\ellip y-{-1}2$, respectivamente, producen

ingrese la descripción de la imagen aquí

Si realmente necesita una versión más sofisticada que admita una macro, le sugiero no poner la macro en el exponente y, en su lugar, simplemente reemplazarla x^con \csuse{#1}:

\newcommand\fancyellip[4]{\csuse{#1}{#3}#2\dots#2\csuse{#1}{#4}}

de modo que ahora $\fancyellip{xint}-{1}2$ produce

ingrese la descripción de la imagen aquí

para una definición apropiada de \xint.

Aquí está el código completo:

\documentclass{article}

\newcommand\ellip[4]{{#1}^{#3}#2\dots#2{#1}^{#4}}

\usepackage{etoolbox}
\newcommand\fancyellip[4]{\csuse{#1}{#3}#2\dots#2\csuse{#1}{#4}}
\newcommand\xint[1]{\int_{0}^{#1}x\,dx}

\begin{document}

  $\ellip x+04$

  $\ellip y-{-1}2$

  \bigskip

  $\fancyellip{xint}-{1}2$
\end{document}

Respuesta4

mi macro

\replaceiandreplicate{<term with i>}%
                     {<loop-start-index>}%
                     {<loop-end-index>}%
                     {<separator>}%
                     {<end index>}

presentado en la discusiónCódigo de bucle para sumas repetidasy en la discusión¿Cómo crear un comando para automatizar la creación de productos similares a la factorización prima?podría ser de su interés:

\documentclass{article}

\makeatletter
%%=============================================================================
%% Paraphernalia:
%%    \UD@firstoftwo, \UD@secondoftwo,
%%    \UD@PassFirstToSecond, \UD@Exchange, \UD@removespace
%%    \UD@CheckWhetherNull, \UD@CheckWhetherBrace,
%%    \UD@CheckWhetherLeadingSpace, \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
\newcommand\UD@removespace{}\UD@firstoftwo{\def\UD@removespace}{} {}%
%%-----------------------------------------------------------------------------
%% 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>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\string{\expandafter
  \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@secondoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument's first token is a catcode-1-character
%%.............................................................................
%% \UD@CheckWhetherBrace{<Argument which is to be checked>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has leading
%%                        catcode-1-token>}%
%%                      {<Tokens to be delivered in case that argument
%%                        which is to be checked has no leading
%%                        catcode-1-token>}%
\newcommand\UD@CheckWhetherBrace[1]{%
  \romannumeral0\expandafter\UD@secondoftwo\expandafter{\expandafter{%
  \string#1.}\expandafter\UD@firstoftwo\expandafter{\expandafter
  \UD@secondoftwo\string}\expandafter\expandafter\UD@firstoftwo{ }{}%
  \UD@firstoftwo}{\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether brace-balanced argument starts with a space-token
%%.............................................................................
%% \UD@CheckWhetherLeadingSpace{<Argument which is to be checked>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is a
%%                               space-token>}%
%%                             {<Tokens to be delivered in case <argument
%%                               which is to be checked>'s 1st token is not
%%                               a space-token>}%
\newcommand\UD@CheckWhetherLeadingSpace[1]{%
  \romannumeral0\UD@CheckWhetherNull{#1}%
  {\expandafter\expandafter\UD@firstoftwo{ }{}\UD@secondoftwo}%
  {\expandafter\UD@secondoftwo\string{\UD@CheckWhetherLeadingSpaceB.#1 }{}}%
}%
\newcommand\UD@CheckWhetherLeadingSpaceB{}%
\long\def\UD@CheckWhetherLeadingSpaceB#1 {%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@secondoftwo#1{}}%
  {\UD@Exchange{\UD@firstoftwo}}{\UD@Exchange{\UD@secondoftwo}}%
  {\UD@Exchange{ }{\expandafter\expandafter\expandafter\expandafter
   \expandafter\expandafter\expandafter}\expandafter\expandafter
   \expandafter}\expandafter\UD@secondoftwo\expandafter{\string}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%
%%   \UD@ExtractFirstArg{ABCDE} yields  {A}
%%
%%   \UD@ExtractFirstArg{{AB}CDE} yields  {AB}
%%.............................................................................
\newcommand\UD@RemoveTillUD@SelDOm{}%
\long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
\newcommand\UD@ExtractFirstArg[1]{%
  \romannumeral0%
  \UD@ExtractFirstArgLoop{#1\UD@SelDOm}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}%
  { #1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%
%%=============================================================================
%% \DefineReplacementMacro{<replacement-macro>}%
%%                        {<internal helper-macro>}%
%%                        {<single non-explicit-space/non-explicit-brace-token to replace>}%
%%
%%  defines <replacement-macro> to fetch two arguments,
%%  #1 = <replacement for item to replace>
%%  #2 = <token sequence with item to replace>
%%  , and to deliver after two expansion-steps:
%%  <token sequence with all instances of 
%%  <single non-explicit-space/non-explicit-brace-token to replace> replaced 
%%  by <replacement for item to replace>. >
%%
%% Internally an <internal helper-macro> is needed.
%%
%%  (!!! <replacement-macro> does also replace all pairs of matching 
%%       explicit character tokens of catcode 1/2 by matching brace-tokens!!!
%%       Under normal circumstances this is not a problem as under normal
%%       circumstances { and } are the only characters of catcode 1 respective 2.)
%%-----------------------------------------------------------------------------
\newcommand\DefineReplacementMacro[3]{%
  \newcommand#2{}\long\def#2##1#3{}%
  \newcommand#1[2]{%
    \romannumeral0\UD@ReplaceAllLoop{##2}{##1}{}{#2}{#3}%
  }%
}%
\newcommand\UD@ReplaceAllLoop[5]{%
  \UD@CheckWhetherNull{#1}{ #3}{%
    \UD@CheckWhetherLeadingSpace{#1}{%
       \expandafter\UD@ReplaceAllLoop
       \expandafter{\UD@removespace#1}{#2}{#3 }{#4}{#5}%
    }{%
      \UD@CheckWhetherBrace{#1}{%
        \expandafter\expandafter\expandafter\UD@PassFirstToSecond
        \expandafter\expandafter\expandafter{%
        \expandafter\UD@PassFirstToSecond\expandafter{%
            \romannumeral0\expandafter\UD@ReplaceAllLoop
            \romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{#2}{}{#4}{#5}%
        }{#3}}%
        {\expandafter\UD@ReplaceAllLoop\expandafter{\UD@firstoftwo{}#1}{#2}}%
        {#4}{#5}%
      }{%
       \expandafter\UD@CheckWhetherNoReplacement
       \romannumeral0\UD@ExtractFirstArgLoop{#1\UD@SelDOm}{#1}{#2}{#3}{#4}{#5}%
      }%
    }%
  }%
}%
\newcommand\UD@CheckWhetherNoReplacement[6]{%
  \expandafter\UD@CheckWhetherNull\expandafter{#5#1#6}%
  {%
    \expandafter\UD@ReplaceAllLoop
    \expandafter{\UD@firstoftwo{}#2}{#3}{#4#1}{#5}{#6}%
  }{%
    \expandafter\UD@ReplaceAllLoop
    \expandafter{\UD@firstoftwo{}#2}{#3}{#4#3}{#5}{#6}%
  }%
}%
%%=============================================================================
%% \UD@ReplaceAlli -- Replace all "i" in undelimited Argument:
%%
%%   \UD@ReplaceAlli{<replacement for i>}{<token sequence with i>}
%%   yields  <token sequence with all i replaced by replacement for i>
%%
%%  <replacement for i> may contain i.
%%
%%  (This routine does also replace all pairs of matching explicit 
%%   character tokens of catcode 1/2 by matching braces!!!)
%%
%%  The letter "i" as item to replace is hard-coded.
%%  You cannot replace öetters other than I with this macro.
%%.............................................................................
\DefineReplacementMacro{\UD@ReplaceAlli}{\UD@gobbletoi}{i}%
%%
%%=============================================================================
%% \replaceiandreplicate{<term with i>}%
%%                      {<loop-start-index>}%
%%                      {<loop-end-index>}%
%%                      {<separator>}%
%%                      {<end index>}
%%
%% e.g., 
%%
%%  \replaceiandreplicate{p_i^{\epsilon_i}}{1}{3}{\cdots}{n}
%%.............................................................................
\newcommand\replaceiandreplicate[5]{%
   \romannumeral0\expandafter\expandafter
                 \expandafter            \UD@Exchange
                 \expandafter\expandafter
                 \expandafter{%
                 \UD@ReplaceAlli{#5}{#1}%
   }{%
     \replaceiandreplicateloop{#3}{#2}{#1}#4%
   }%
}%
\newcommand\replaceiandreplicateloop[3]{%
  \ifnum#1<#2 %
    \expandafter\UD@firstoftwo
  \else
   \expandafter\UD@secondoftwo
  \fi
  { }{%
    \expandafter\expandafter
    \expandafter            \UD@Exchange
    \expandafter\expandafter
    \expandafter{%
       \UD@ReplaceAlli{#1}{#3}%
    }{%
      \expandafter\replaceiandreplicateloop
      \expandafter{\number\numexpr\number#1-1\relax}{#2}{#3}%
    }%
  }%
}%
\makeatother

\parindent=0ex

\begin{document}

\begin{verbatim}
$\replaceiandreplicate{x^{i}}{0}{0}{+\ldots+}{5}$
\end{verbatim}

yields:\bigskip

$\replaceiandreplicate{x^{i}}{0}{0}{+\ldots+}{5}$

\bigskip\hrule

\begin{verbatim}
$\replaceiandreplicate{\if i0\else+\fi x^{i}}{0}{4}{}{5}$
\end{verbatim}

yields:\bigskip

$\replaceiandreplicate{\if i0\else+\fi x^{i}}{0}{4}{}{5}$

\bigskip\hrule

\begin{verbatim}
$\replaceiandreplicate{\ifnum i=-2 \else+\fi x^{\ifnum i<0(i)\else i\fi}}{-2}{4}{}{5}$
\end{verbatim}

yields:\bigskip

$\replaceiandreplicate{\ifnum i=-2 \else+\fi x^{\ifnum i<0(i)\else i\fi}}{-2}{4}{}{5}$

\bigskip\hrule

\begin{verbatim}
$\replaceiandreplicate{p_{i}^{\epsilon_{i}}}{1}{3}{\cdots}{n}$
\end{verbatim}

yields:\bigskip

$\replaceiandreplicate{p_{i}^{\epsilon_{i}}}{1}{3}{\cdots}{n}$

\bigskip\hrule

\begin{verbatim}
$\replaceiandreplicate{\if in+\fi p_{i}^{\epsilon_{i}}\if in\else+\fi}%
                      {1}%
                      {3}%
                      {\cdots}%
                      {n}$
\end{verbatim}

yields:\bigskip

$\replaceiandreplicate{\if in+\fi p_{i}^{\epsilon_{i}}\if in\else+\fi}{1}{3}{\cdots}{n}$

\end{document}

ingrese la descripción de la imagen aquí

No anide llamadas a \replaceiandreplicatedentro del primer argumento de \replaceiandreplicate. ;-)

información relacionada