原始问题

原始问题

原始问题

我想创建一个元命令来创建新的投影命令。具体来说,\newproj{\cmd}{<n>}{<m>}应该创建\cmd一个新的<n>(强制)参数命令,该命令始终扩展到第<m>th 个参数。

例如,如果我们有\newproj{\fst}{2}{1}\newproj{\snd}{2}{2},那么\fst{x}{y}应该扩展为,x\snd{x}{y}应该扩展为y

以下是我的尝试:

\documentclass{article}

\newcommand*{\newproj}[3]{%
  \newcommand*#1[#2]{%
    \expandafter#\expandafter##3%
  }%
}

\newproj{\fst}{2}{1}
\newproj{\snd}{2}{2}

\begin{document}
\begin{tabular}{ll}
\verb^\fst{x}{y}^:& \fst{x}{y} \\
\verb^\snd{x}{y}^:& \snd{x}{y}
\end{tabular}
\end{document}

不幸的是,这会出现错误“定义中的参数编号非法” \newproj<to be read again> \expandafter如何将参数用作某些整数或元​​参数的函数?

扩展问题:通过宏间接调用

A.Ellett 和 Hendrik Vogt 建议使用\newcommand*#1[#2]{###3}因为##扩展为#。如果将正整数作为 传递给 ,则此方法非常有效#3\newproj但是,假设我将宏作为 传递给\newproj#3如何使用宏扩展来动态选择参数?

例如,下面的代码应该能产生正确的结果。但是,它给出了错误“定义中的参数编号非法\fst<to be read again> \i”。

\documentclass{article}

\newcommand*{\newproj}[3]{%
  \newcommand*#1[#2]{%
    \expandafter###3%
  }%
}

\def\i{1}
\newproj{\fst}{2}{\i}
\newproj{\snd}{2}{2}

\begin{document}
\begin{tabular}{ll}
\verb^\fst{x}{y}^:& \fst{x}{y} \\
\verb^\snd{x}{y}^:& \snd{x}{y}
\end{tabular}
\end{document}

答案1

在此处输入图片描述

您只想完全扩展两个参数以\number获取它们的十进制扩展,同时避免扩展其他所有内容(对于这种情况,toks 寄存器很有用)

\documentclass{article}

\newcommand*{\newproj}[3]{%
  \toks0{\newcommand*#1}%
  \edef\tmp{\the\toks0[\number#2]{####\number#3}}%
\tmp
  }

\def\i{1}
\newproj{\fst}{2}{\i}
\newproj{\snd}{2}{2}

\begin{document}
\begin{tabular}{ll}
\verb^\fst{x}{y}^:& \fst{x}{y} \\
\verb^\snd{x}{y}^:& \snd{x}{y}
\end{tabular}
\end{document}

答案2

这是开始

\documentclass{article}
\newcommand{\newproj}[3]{%
    \expandafter\newcommand\csname #1\expandafter\endcsname[#2]{###3}
}
\pagestyle{empty}
\begin{document}

Hello

\newproj{helloworldapplesauce}{4}{3}

\helloworldapplesauce{a}{b}{c}{d}
\end{document}

或者您可以尝试这样做(按照@HendrikVogt 的建议)

\newcommand{\newproj}[3]{\newcommand{#1}[#2]{###3}}

也应该可以

无论采用哪种方法,您都可能需要确保传递到参数中的值是数字,并且传递到定义函数的第三个参数中的值不大于第二个参数。

答案3

\documentclass[12pt]{article}
\usepackage{catoptions}
\makeatletter
% \generateparams is not any costlier than using \newcommand:
\new@def*\generateparams#1#2{%
  \ifnum#1<\numexpr#2+1####\number#1%
    \expandafter\generateparams
    \expandafter{\number\numexpr#1+1\expandafter}%
    \expandafter{\number#2\expandafter}%
  \fi
}
\robust@def*\newproj#1#2#3{%
  \@ifdefinable#1\relax
  \cptexpanded{\def\noexpand#1\generateparams1{#2}{#####3}}%
}

% Examples of \newproj:
\def\one{1}
\newproj{\fst}{2}{\one}
\newproj{\snd}{2}{2}

% Using a loop to avoid repeating \newproj for every new definition:
\robust@def*\NewProj#1{%
  \cptforeach \x/\y/\z \in#1\do{%
    \cptexpandsecond\newproj{\noexpandcsn{\x}{\y}{\z}}%
  }%
}

% Examples of \NewProj:
\NewProj{fstb/2/\one, sndb/2/2}

\makeatother

% Let us print the examples:
\begin{document}
\begin{tabular}{ll}
\verb^\fst{x}{y}^:& \fst{x}{y} \\
\verb^\snd{x}{y}^:& \snd{x}{y} \\
\verb^\fstb{x}{y}^:& \fstb{x}{y} \\
\verb^\sndb{x}{y}^:& \sndb{x}{y}
\end{tabular}
\end{document}

在此处输入图片描述

答案4

可以expl3定义一个临时宏,并将所需的宏设置为等于它。什么都没有留下,因为我们在一个组中执行此操作并利用它\cs_new_eq:NN(此处为\cs_new_eq:Nc变体)进行全局定义。

我用来\prg_replicate:nn构建所需数量的参数。

可能的变化:如果需要非长宏,则使用\cs_set_nopar:cx而不是\cs_set:cx

两个参数都可以是宏或整型变量。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\newproj}{mmm}
 {% #1 is the name of a command
  % #2 is the number of arguments
  % #3 is the argument to choose
  \group_begin:
  \tl_set:Nx \l_tmpa_tl { __deyoung_temp: \prg_replicate:nn { #2 } { n } }
  \cs_set:cx { \l_tmpa_tl } { ## \int_eval:n { #3 } }
  \cs_new_eq:Nc #1 { \l_tmpa_tl }
  \group_end:
}
\ExplSyntaxOff

\newcommand\idx{1} \newcounter{baz} \setcounter{baz}{2}
\newproj{\fst}{2}{\idx}
\newproj{\snd}{2}{\value{baz}}

\begin{document}

\verb^\fst{x}{y}^: \fst{x}{y}

\verb^\snd{x}{y}^: \snd{x}{y}

Is it expandable? \edef\test{\fst{x}{y}}
\texttt{\meaning\test}

\newproj{\foo}{9}{4}\texttt{\meaning\foo}

\end{document}

在此处输入图片描述

相关内容