最近在研究tikzlings宏包的代码时,有段latex3代码看不懂,我试图按照自己的理解简化一下,但是编译不通过。这段代码的目的是把一个特定形式的comma list拆解成pgf的key路径。
即,把如下comma list:
\def\animallist{
anteater/anteaters,bat/bats,bear/bears,bee/bees,bug/bugs,cat/cats,chicken/chickens,coati/coatis,elephant/elephants,hippo/hippos,koala/koalas,marmot/marmots,mouse/mice,moles/moles,owl/owls,panda/pandas,penguin/penguins,pig/pigs,rhino/rhinos,sheep/sheep,sloth/sloths,snowman/snowmen,squirrel/squirrels%
}
拆解成:
/anteater,/bat,/bear,/bee,/bug,/cat,/chicken,/coati,/elephant,/hippo,/koala,/marmot,/mouse,/moles,/owl,/panda,/penguin,/pig,/rhino,/sheep,/sloth,/snowman,/squirrel,
这样的一串字符串。以下代码是从tikzlings宏包中提取出来的部分代码,是OK的,可以达成目的。
\documentclass{article}
\usepackage{expl3}
\def\animallist{
anteater/anteaters,
bat/bats,
bear/bears,
bee/bees,
bug/bugs,
cat/cats,
chicken/chickens,
coati/coatis,
elephant/elephants,
hippo/hippos,
koala/koalas,
marmot/marmots,
mouse/mice,
moles/moles,
owl/owls,
panda/pandas,
penguin/penguins,
pig/pigs,
rhino/rhinos,
sheep/sheep,
sloth/sloths,
snowman/snowmen,
squirrel/squirrels%
}
\begin{document}
\ExplSyntaxOn
\cs_new:Npn \tk_iteratesearch:N #1 {
\clist_map_function:NN #1 \__tk_slashed_items:n
}
\cs_new:Npn \__tk_slashed_items:n #1 {
/
\exp_not:N {
\__tk_before_slashsearch:w #1 \s_stop
}
,
}
\cs_new:Npn \__tk_before_slashsearch:w #1 / #2 \s_stop {
\tl_trim_spaces:n {#1}
}
\tk_iteratesearch:N\animallist
\ExplSyntaxOff
\end{document}
这里面的\tk_iteratesearch:N
是三层定义循环嵌套,我主要是卡在把tl1/tl2
里的tl1
提取出来在前后添加/
和,
这里了。我的改动是这样的:
\documentclass{article}
\usepackage{expl3}
\def\animallist{
anteater/anteaters,
bat/bats,
bear/bears,
bee/bees,
bug/bugs,
cat/cats,
chicken/chickens,
coati/coatis,
elephant/elephants,
hippo/hippos,
koala/koalas,
marmot/marmots,
mouse/mice,
moles/moles,
owl/owls,
panda/pandas,
penguin/penguins,
pig/pigs,
rhino/rhinos,
sheep/sheep,
sloth/sloths,
snowman/snowmen,
squirrel/squirrels%
}
\begin{document}
\ExplSyntaxOn
\cs_new:Npn \tk_iteratesearch:N #1 {
\clist_map_function:NN #1 \__tk_before_slashsearch:w
}
\cs_new:Npn \__tk_before_slashsearch:w #1 / #2 \s_stop {
/
\tl_trim_spaces:n {#1}
,
}
\tk_iteratesearch:N\animallist
\ExplSyntaxOff
\end{document}
谁能跟我说说这里面的症结到底在哪么?
我们知道,如果一个宏是使用如下方式定义的:
\def\foo#1\T{something #1 else...}
那么在使用该宏时必须使用 \T
作为(第一个)参数的分隔符,也就是必须使用
\foo balabala\T
如若没有 \T
,TeX 将会报错。
你的代码就是这种错误。
因为使用了 \cs_new:Npn \__tk_before_slashsearch:w #1 / #2 \s_stop
,所以参数分隔符 /
和 \s_stop
是必须给出的。
但是 \clist_map_function:NN <clist> <func>
所做的仅仅是把 <clist>
的 <item>
置于 <func>
之后,也就是
\__tk_before_slashsearch:w <item>
这样 \s_stop
是没有的,所以必须通过一个辅助函数给出,也就是原来 \__tk_slashed_items:n
的作用之一。
因为这里的 \tk_iteratesearch:N
必须可扩展,所以不能使用 \clist_map_inline:Nn
。