如何定义需要超过 18 个参数的命令

如何定义需要超过 18 个参数的命令

这个问题基于这个答案这是
我之前关于值列表在乳胶中。

根据第一个链接,我所面临的参数数量是有限的。

我尝试使用指定的方法并且效果很好。

但是如果我想要超过 18 个参数怎么办?

是否可以递归使用这种方法?

例如,我想定义一个有 25 个参数的函数。是否可以使用以下方法:

\newcommand\ParseOptMenuItemStoreA[9]{%
    \def\tempa{#1}%
    \def\tempb{#2}%
    \def\tempc{#3}%
    \def\tempd{#4}%
    \def\tempe{#5}%
    \def\tempf{#6}%
    \def\tempg{#7}%
    \def\temph{#8}%
    \def\tempi{#9}%
    \ParseOptMenuItemStoreB
}

\newcommand\ParseOptMenuItemStoreB[9]{%
    \def\tempj{#1}%
    \def\tempk{#2}%
    \def\templ{#3}%
    \def\tempm{#4}%
    \def\tempn{#5}%
    \def\tempo{#6}%
    \def\tempp{#7}%
    \def\tempq{#8}%
    \def\tempr{#9}%
    \ParseOptMenuItem
}

\newcommand\ParseOptMenuItem[7]{%
    % Access to arguments #1-#18 via \tempa-\tempr and to argument #19-#25 via #1-#7.
}

我尝试编译它但出现错误:

! Missing number, treated as zero.
<to be read again>
               \protect
l.40 }  

那么我做错了什么?

2015 年 8 月 19 日更新:

我使用了下一个构造来实现我的目标:

\newcommand{\ParseOptMenuItemList}[1]
{
\def\tmplist{#1}%
\@tempcnta=\z@
\@for\tmp:=\tmplist\do{\advance\@tempcnta\@ne
\expandafter\let\csname temp\@roman\@tempcnta\endcsname\tmp
}%
\makebox[\linewidth][r]{%
    \begin{tabular}{lc}
        Possible values: \ifthenelse{\equal{\tempi}{}}{}{& \tempi\\}
        \ifthenelse{\equal{\tempii}{}}{}{& \tempii\\}
        \ifthenelse{\equal{\tempiii}{}}{}{& \tempiii\\}
        \ifthenelse{\equal{\tempiv}{}}{}{& \tempiv\\}
        \ifthenelse{\equal{\tempv}{}}{}{& \tempv\\}
        \ifthenelse{\equal{\tempvi}{}}{}{& \tempvi\\}
        \ifthenelse{\equal{\tempvii}{}}{}{& \tempvii\\}
        \ifthenelse{\equal{\tempviii}{}}{}{& \tempviii\\}
        \ifthenelse{\equal{\tempix}{}}{}{& \tempix\\}
        \ifthenelse{\equal{\tempx}{}}{}{& \tempx\\}
        \ifthenelse{\equal{\tempxi}{}}{}{& \tempxi\\}
        \ifthenelse{\equal{\tempxii}{}}{}{& \tempxii\\}
        \ifthenelse{\equal{\tempxiii}{}}{}{& \tempxiii\\}
        \ifthenelse{\equal{\tempxiv}{}}{}{& \tempxiv\\}
        \ifthenelse{\equal{\tempxv}{}}{}{& \tempxv\\}
        \ifthenelse{\equal{\tempxvi}{}}{}{& \tempxvi\\}
        \ifthenelse{\equal{\tempxvii}{}}{}{& \tempxvii\\}
        \ifthenelse{\equal{\tempxviii}{}}{}{& \tempxviii\\}
      Default value: & \tempxix\\
    \end{tabular}
}
}

\ParseOptMenuItemList将值作为逗号分隔的列表。

答案1

与所有其他 Latex 命令不同,使用多个{}会导致界面难以使用,Latex 具有将参数处理为逗号分隔列表的标准功能(\usepackage{array,bm,graphics}例如)。

生成以下内容

argument 24 is: [x]

在终端上确认已捕获参数 24(至少:-)。

\makeatletter
\newcommand\foo[1]{%
\def\tmplist{#1}%
\@tempcnta=\z@
\@for\tmp:=\tmplist\do{\advance\@tempcnta\@ne
\expandafter\let\csname temp\@roman\@tempcnta\endcsname\tmp
}%
\typeout{argument 24 is: [\tempxxiv]}%
}


\makeatother


\foo{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}

\stop

答案2

这是另一个,您必须调用这个\definemanyarguments{24},然后接下来的 24 个参数将被“保存”,然后您可以使用它们\argument{12}

这是完整的文档。

\documentclass{scrartcl}

\newcounter{manyarguments}
\providecommand\gobbleone[1]{}
\providecommand\useone[1]{#1}
\newcommand*\definemanyarguments[1]
  {\setcounter{manyarguments}{0}%
   \def\nextargument{\stepcounter{manyarguments}%
     \ifnum\value{manyarguments}>#1 \expandafter\gobbleone
     \else\expandafter\useone\fi
     {\afterassignment\nextargument
      \csdefignorespaces{argumentnumber\arabic{manyarguments}}}}%
   \nextargument}
\newcommand\csdefignorespaces[2]{\expandafter\def\csname#1\endcsname{#2}}
\newcommand*\argument[1]{\csname argumentnumber#1\endcsname}

\begin{document}

\definemanyarguments{25}
  {1}{2}{3}{4}{5}{6}{7}{8}{9}{a}{b}{c}{d}{e}{f}{g}{h}{i}
  {A}{B}{C}{D}{E}{F}{last argument}

[\argument{2}]
[\argument{12}]
[\argument{23}]
[\argument{24}]
[\argument{25}]

\end{document}

答案3

我认为使用带有超过三或四个参数的宏是没有道理的。但是,这里有一个\newextracommand可以接受任意数量参数的实现(受 TeX 的算术能力限制,因此不超过 2 30 –1,当然也受内存限制)。

\documentclass{article}

\newcommand\newextracommand[3]{%
  \newcounter{extra\string#1}%
  \newcommand{#1}{\extrarecurse{#1}{#2}{#3}}%
}

\newcommand\extrarecurse[3]{%
  \setcounter{extra\string#1}{1}%
  \grabarg{#1}{#2}{#3}%
}

\makeatletter
\newcommand{\grabarg}[4]{%
  \ifnum#2<\value{extra\string#1}\relax
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi
  {%
   \@namedef{arg@\romannumeral\value{extra\string#1}}{#4}
   \stepcounter{extra\string#1}%
   \grabarg{#1}{#2}{#3}
  }
  {#3}%
}
\newcommand\doarg[1]{\csname arg@\romannumeral#1\endcsname}
\makeatother

\newextracommand{\foo}{20}{%
  \doarg{1}--\doarg{2}--\doarg{3}--\doarg{4}--%
  \doarg{5}--\doarg{6}--\doarg{7}--\doarg{8}--%
  \doarg{9}--\doarg{10}--\doarg{11}--\doarg{12}--%
  \doarg{13}--\doarg{14}--\doarg{15}--\doarg{16}--%
  \doarg{17}--\doarg{18}--\doarg{19}--\doarg{20}%
}

\begin{document}

\foo{a}{b}{c}{d}{e}{f}{g}{h}{i}{j}{k}{l}{m}{n}{o}{p}{q}{r}{s}{t}

\end{document}

定义主体中的参数用 表示\doarg{<number>}

在此处输入图片描述

不要尝试在表格单元格中使用此类命令,也不要尝试嵌套调用如此定义的相同命令。

答案4

它似乎对我有用:

\documentclass{article}

\newcommand\ParseOptMenuItemStoreA[9]{%
    \def\tempa{#1}%
    \def\tempb{#2}%
    \def\tempc{#3}%
    \def\tempd{#4}%
    \def\tempe{#5}%
    \def\tempf{#6}%
    \def\tempg{#7}%
    \def\temph{#8}%
    \def\tempi{#9}%
    \ParseOptMenuItemStoreB
}

\newcommand\ParseOptMenuItemStoreB[9]{%
    \def\tempj{#1}%
    \def\tempk{#2}%
    \def\templ{#3}%
    \def\tempm{#4}%
    \def\tempn{#5}%
    \def\tempo{#6}%
    \def\tempp{#7}%
    \def\tempq{#8}%
    \def\tempr{#9}%
    \ParseOptMenuItem
}

\newcommand\ParseOptMenuItem[7]{%
    % Access to arguments #1-#18 via \tempa-\tempr and to argument #19-#25 via #1-#7.
    before

    #7

    tempj: \tempj

    tempi: \tempi

    after
}

\begin{document}
\ParseOptMenuItemStoreA{1}{2}{3}{4}{5}{6}{7}{8}{9}{a}{b}{c}{d}{e}{f}{g}{h}{i}{A}{B}{C}{D}{E}{F}{last argument}
\end{document}

但你可能不应该这么做,理由 David Carlisle 和 Christian Hupfer 已经给出了。

相关内容