以下是 MWE:
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\dim_new:N \l__xchoices_coffin_join_horizontal_sep_dim
\str_new:N \l__xchoices_coffin_current_label_pos_str
\str_set:Nn \l__xchoices_coffin_current_label_pos_str {left}
\cs_new:Npn \__xchoices_label_hsep_init:N #1
{
\dim_set:Nn \l__xchoices_coffin_join_horizontal_sep_dim
{
\str_if_in:NnTF #1 {left}
{ 5pt }
{
\str_if_in:NnTF #1 {right}
{-5pt}
{0pt}
}
}
}
\__xchoices_label_hsep_init:N
\l__xchoices_coffin_current_label_pos_str
% \dim_use:N \l__xchoices_coffin_join_horizontal_sep_dim
\ExplSyntaxOff
\end{document}
但编译失败,致命消息是:
Missing number, treated as zero
Illegal unit of measure (pt inserted)
我不知道这是怎么回事。
答案1
关于宏扩展的简短课程
TeX 令牌可以是可扩展或者不可扩张. 宏(用\def
或其变体定义的宏,例如\cs_new:Npn
)属于第一类,也是一些原语。
当 TeX 处理输入时,它首先构建标记,然后继续扩展标记(如果可能)。如果不可能,它会将根据找到的不可扩展标记的语法规则吸收的标记发送到下一阶段(这不在用户的控制范围内)。
\dim_set:Nn
例如,该指令是不可扩展的。在传统的 TeX 术语中,有类似的东西
\newdimen\foo
\foo=\dimexpr ... \relax
令牌\foo
不可扩展,因此它被发送到下一个阶段,在那里它被识别为寄存器<dimen>
,因此 TeX 根据语法规则请求更多输入,这些规则允许=
并希望得到可以解释为(固定)长度的东西。好的,\dimexpr
很好,但它本身不可扩展。同样的故事,它被发送上去,然后请求更多输入。
在这种情况下,会执行宏扩展,因此如果您在为 提供新标记的同时\def\baz{640pt}
找到了 ,TeX会很高兴。但是,如果它发现某些内容不符合 的语法规则,那么它将停止寻找更多标记,并且下一阶段必须使用它已有的内容。\baz
\dimexpr
\dimexpr
你的情况出了什么问题?
的第二个参数必须\dim_set:Nn
仅包含在扩展过程结束时只留下符合语法的不可扩展标记的标记\dimexpr
。
不幸的是,\str_if_in:NNTF
没有。你可以从interface3
手册中没有星号的事实推断出来。因此,它的处理不能(实际上确实如此)立刻提供最后两个参数之一的记录。
你能做什么?
在图片中我还添加了\str_case:nn(TF)
显示此套件中的说明是可擴展。
如果您的字符串变量只预计包含left
或right
(因此无需使用测试\str_if_in:nnTF
),则可以使用\str_case:VnF
:
\dim_set:Nn \l__xchoices_coffin_join_horizontal_sep_dim
{
\str_case:VnF #1
{
{left}{5pt}
{right}{-5pt}
}
{0pt}
}
否则你需要\dim_set:Nn
在案例里面有说明
\str_if_in:NnTF #1 {left}
{
\dim_set:Nn \l__xchoices_coffin_join_horizontal_sep_dim {5pt}
}
{
\str_if_in:NnTF #1 {right}
{
\dim_set:Nn \l__xchoices_coffin_join_horizontal_sep_dim {-5pt}
}
{
\dim_set:Nn \l__xchoices_coffin_join_horizontal_sep_dim {0pt}
}
}
无论哪种情况,\cs_new:Npn \__xchoices_label_hsep_init:N #1
都应该
\cs_new_protected:Npn \__xchoices_label_hsep_init:N #1
因为这个函数执行不可扩张动作。