我有两个问题:
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的理解真的是太深刻了,真正做到了格物致知,解答的太贴心了,非常感谢!