这有效:
\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}