关于latex3里的\cs_new:Npn分解特定形式的comma list的问题

发布于 2021-11-19 19:43:21

最近在研究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}

谁能跟我说说这里面的症结到底在哪么?

查看更多

关注者
0
被浏览
191
雾月
雾月 2021-11-20

我们知道,如果一个宏是使用如下方式定义的:

\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

2 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览