\def\foo#1:#2:#3 可以用 \foo{a:b:c} 调用,但不能用 \foo{a:\bc} 调用

\def\foo#1:#2:#3 可以用 \foo{a:b:c} 调用,但不能用 \foo{a:\bc} 调用

这有效:

\def\myfunc#1{\expandafter\myfuncdoit#1\relax}
\def\myfuncdoit#1:#2:#3\relax{ First: (#1), Second: (#2), Third (#3) }

\foreach \p in {x:foo:int,y:bar:float,z:baz:bool}{ (\myfunc{\p}) }

它产生

第一个:(x),第二个:(foo),第三个(int)第一个:(y),第二个:(bar),第三个(float)第一个:(z),第二个:(baz),第三个(bool)

但是,我需要\foreach通过以下列表调用它,具有共享的第一个字符串:

\foreach \p in {foo:int,bar:float,baz:bool}{ (\myfunc{abc:\p}) }

我预计这会产生

第一个:(abc),第二个:(foo),第三个(int)第一个:(abc),第二个:(bar),第三个(float)第一个:(abc),第二个:(baz),第三个(bool)

但它不能编译

Runaway argument?
float,baz:bool, \pgffor@stop , 
Paragraph ended before \myfuncdoit was complete.
<to be read again> 
                   \par

为什么它不起作用?我该如何修复它?谢谢。

答案1

您必须确保在扫描参数的位置\myfuncdoit,所有分隔符都已到位。此时不会发生任何扩展。

你可以那样做。

\newcommand\myfuncx[2]{\myfuncdoit#2:#1\relax}

\foreach \p in {foo:int,bar:float,baz:bool}
  { (\expandafter\myfuncx\expandafter{\p}{abc}) }

在此处输入图片描述

\documentclass{article}
\usepackage{pgffor}
\newcommand\myfuncx[2]{\myfuncdoit#2:#1\relax}
\def\myfuncdoit#1:#2:#3\relax{ First: (#1), Second: (#2), Third (#3) }
\begin{document}
\foreach \p in {foo:int,bar:float,baz:bool}
      { (\expandafter\myfuncx\expandafter{\p}{abc}) }
\end{document}

答案2

我之前的答案的一个简单扩展:

\documentclass{article}
\usepackage{xparse}

\NewDocumentCommand{\myfuncthree}{>{\SplitArgument{2}{:}}m}{%
  \myfuncsplitthree#1%
}
\NewDocumentCommand{\myfuncsplitthree}{mmm}{%
  First: (#1), Second: (#2), Third: (#3).%
}

\ExplSyntaxOn
\NewDocumentCommand{\cycle}{ m +m }
 {
  \clist_map_inline:nn { #1 } { #2 }
 }
\ExplSyntaxOff

\begin{document}

\cycle{foo:int, bar:float, baz:bool}{\myfuncthree{abc:#1}\par}

\end{document}

在此处输入图片描述

如果你改为调用

\cycle{foo:int, bar:float, baz:bool}{\myfuncthree{#1:zzz}\par}

您获得了预期的结果。

在此处输入图片描述

答案3

这是一个使用\edef扩展参数的解决方案\myfunc

\documentclass{article}
\usepackage{pgffor}

\makeatletter
\def\myfunc#1{\edef\my@tmp{#1}\expandafter\myfuncdoit\my@tmp\relax}
\def\myfuncdoit#1:#2:#3\relax{ First: (#1), Second: (#2), Third (#3) }
\makeatother

\begin{document}
\foreach \p in {x:foo:int,y:bar:float,z:baz:bool}{ (\myfunc{\p})\par }
\foreach \p in {foo:int,bar:float,baz:bool}{ (\myfunc{abc:\p})\par }
\end{document}

相关内容