我有两个问题:
1.忽略字符类代码是指何意?
interface3中l3prop模块里开篇讲到:“属性列表中每一项的<键>被\tl_to_str:n处理为字符串,这意味着它的类代码被忽略”(下图中标黄部分)。原文截取图如下:
我查了一下\tl_to_str:n本质上是\detokenize,它将所接收的内容中除空格外的所有字符的类代码都转化为12,按interface3手册中的意思,是否意味着将字符类代码设置为12就意味着忽略类代码?如果不是,那么所谓的忽略字符类代码是指何意?
2.对函数\prop_set_from_keyval:Nn <属性列表> {<键值对>}如何处理其第二个参数的疑惑?
该函数用法的原文截取图如下:
里面说到,此函数第二个参数里的<key>和<value>都能包含:空格、等号或逗号,请问系统是如何“trimmed”空格而做到的(我没太理解这一步操作)?
另外,该函数原文解释中的“这一函数(\prop_set_from_keyval:Nn)能够正确处理=和,,如果它们的类代码为12或活动符则对其进行标记”(上图中标黄部分)。请问\prop_set_from_keyval:Nn第二个参数{<key>=<value>,...}里的=和,(也就是<value>前后的=和,)与<key>中或<value>中所包含的=和,是如何区别的以至于“系统能够正确处理它们”?还有,前面所说的标记,标记的是<key>和<value>外围的=和,还是其内所包含的=和,?
1.
忽略类别码(catcode)是指在比较两个 token list 时,先把它们 \detokenize,然后再按字典序比较,(也就是不比较它们的类别码,因为经过 \detokenize 后,同一字符的类别码都相同,控制序列也没有了),即使用 \str_if_eq:...,反之,则使用 \tl_if_eq:...。
\str_set:Nn \a { ~ \\ $ }
\tl_set:Nn \b { ~ \\ $ }
\tl_set:Nx \c { \c_space_tl \c_backslash_str \c_backslash_str \c_dollar_str }\a 和 \c 的值完全相同:即,它们的长度相同且每一对字符的 (catcode,charcode) 完全相同,也就是 \tl_if_eq:NNTF \a \c 返回 true 分支。\b 和 \c 的长度不同,即 \tl_if_eq:NNTF \b \c 返回 false 分支。但对 \b 的值使用 \detokenize(\tl_to_str:n)之后,就变成了 \c(的值),也就是 \str_if_eq:NNTF \b \c 返回 true 分支。
prop 中 key 的比较就是使用 \str_if_eq:...。
“忽略类别码”只有在比较 token list 时才有意义。
(在 (u)pTeX 中应该是 kcatcode 而非 catcode。)
2.\prop_set_from_keyval:Nn 是使用 \keyval_parse:nnn 实现的。\tl_trim_spaces:n 移除首尾空格,但在此之后,如果结果是一个正确嵌套的组(如 {a } 是,{a}{b} 不是),并不会继续移除外层的 {}。而 \keyval_parse:nnn 在分别解析 key 和 value 时则会继续移除外层的 {}。
{~a~}~ = ~bc~ , % key 是 " a ",value 是 "bc"
~a~ = {~bc~}~ , % key 是 "a",value 是 " bc "
{ a= } = {b=c} , % key 是 "a=",value 是 "b=c"
{ a, } = {b,} , % key 是 "a,",value 是 "b,"
a =, % key 是 "a",value 是 ""
a, % key 是 "a",没有 value这样,key 和 value 中可以包含空格、逗号和等号
如上例。\keyval_parse:nnn 并不会修改 key 和 value 的类别码。
3.
某些情况下可能会改变 =, 的类别码为 13(active),这样解析键值时就会出错,比如 keyval 宏包。\keyval_parse:nnn 专门处理了这种情况。方法是递归。
先以 active , 分割出 n 项,然后对这 n 项分别以 other , 分割,由此得到 key=val。再对 = 施以类似的操作,由此得到每个 key 与 对应的 value。
感谢雾月大佬,您对L3的理解真的是太深刻了,真正做到了格物致知,解答的太贴心了,非常感谢!