如何定義將巨集的定義作為參數的宏

如何定義將巨集的定義作為參數的宏

我們想定義一個\ellipsis帶有四個參數並具有以下行為的巨集:

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

和輸出:

在此輸入影像描述

模式字串#DUMMY#(不必是這個確切的字串)必須替換為第二個和第三個參數。所以第一個參數就是巨集本身的定義。


我們嘗試了一些方法,但最終總是使用兩個不同的巨集來獲得所需的行為。例如做

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

\csuse這使用包中的控制序列電子工具箱(我們可以使用任何軟體包)。

我們希望在短短的時間內做到這一點指令,因此,內部巨集 ( ) 的定義x^{#DUMMY}需要放置在較大巨集的定義中。

請包括您可能有的關於如何執行此操作的任何想法。

答案1

這是我的答案的改編如何發出命令來自動創建類似素因式分解的產品?

\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}

在此輸入影像描述

如果您願意使用#1佔位符,則可以簡化:

\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}

答案2

在此輸入影像描述

對於參數位於佔位符末尾的範例,您不需要定義任何內部命令,但對於一般情況,該形式\ellipsisb將任何單參數命令定義的主體作為第一個參數。這允許最後顯示 0^2...5^2 形式。

\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}

答案3

也許我不明白你想要什麼,但據我所知你不需要\csuse在這裡並且可以定義:

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

這樣 $\ellip x+04$ 和 $\ellip y-{-1}2$ 分別產生

在此輸入影像描述

如果您確實需要一個支援巨集的更高級版本,那麼我建議不要將巨集放在指數中,而只需替換x^\csuse{#1}

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

這樣現在 $\fancyellip{xint}-{1}2$ 產生

在此輸入影像描述

的適當定義\xint

這是完整的程式碼:

\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}

答案4

我的宏

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

討論中提出重複求和的循環程式碼並在討論中如何發出命令來自動創建類似素因式分解的產品?您可能感興趣:

\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}

在此輸入影像描述

請不要將呼叫嵌套 \replaceiandreplicate在 的第一個參數內\replaceiandreplicate。 ;-)

相關內容