为什么我们不能使用 \define 的值作为 \switchtobodyfont[...] 的参数?

为什么我们不能使用 \define 的值作为 \switchtobodyfont[...] 的参数?

这是对问题的后续回答在 ConTeXt 中 \def 和 \define 相同吗?

mkiv ConTeXt(TeX Live 2013 版本)中的这段代码:

\define\smallfontsize{8.1pt}
\starttext
foo \switchtobodyfont[\smallfontsize] bar
\stoptext

给出以下输出,包括一个错误:

...
fonts           > bodyfont '\smallfontsize ' is defined (can better be done global)
fonts           > bodyfont '9.72pt' is defined (can better be done global)
fonts           > bodyfont '6.48pt' is defined (can better be done global)
! LuaTeX error [string "\directlua "]:1: invalid escape sequence near '\s'.

system          > tex > error on line 3 in file C:/Users/Huttar/Documents/work/tex/test-define.tex: LuaTeX error  ...

1     \define\smallfontsize{8.1pt}
2     \starttext
3 >>  foo \switchtobodyfont[\smallfontsize] bar
4     \stoptext
5     


\ctxcommand #1^^@-\directlua {commands.#1}

\font_helpers_low_level_define ..._designsize " )}
                                                  \edef \somefontspec {at \n...
\font_helpers_trigger_define ..._identifier_class 
                                                  \csname \v_font_identifier...
\applyfontclassstrategies ...\fontface \endcsname 
                                                  \else \expandafter \font_h...
\font_helpers_synchronize_font ...classstrategies 
                                                  \fi \setfalse \c_font_auto...
\rm f-\ifmmode \mathrm \else \normalrm 
                                       \fi 
...
l.3 foo \switchtobodyfont[\smallfontsize]
                                        bar

但是如果我们\define将开头的 改为\def,错误就会消失。答案是https://tex.stackexchange.com/a/55778/6973虽然有用,但似乎只描述了宏参数方面的差异。在这种情况下,没有参数,为什么使用 定义\switchtobodyfont[\smallfontsize]时会失败?我们希望更好地理解这一点,以便将来避免以不安全的方式使用。\smallfontsize\define\define

次要问题是这样的(授人以渔!)...当面对上述错误消息时,我们不知所措,不知道问题是什么。诊断似乎没有以我们能理解的方式指出问题所在。(它给了我们正确的行号,但实际行号\switchtobodyfont[\smallfontsize]被埋在几个宏调用的深处,还有许多其他代码。)我们之所以能找到解决方案,是因为一位同事做了很多反复试验,注释掉代码以找到有问题的行,而且我们很久以前就遇到过类似的问题。输出中是否有我们可以学习解释的东西,以便推断问题的原因和解决方案?(或者可以改进诊断消息以更好地提供原因线索吗?)

答案1

\def语创建可扩展的宏,或者至少是将在\edef或内扩展的宏\csname。另一方面,\define使用\protected\def创建受保护的宏。这些在 内部展开\csname,因此不适合用于需要以这种方式展开内容的任何事物。因此,您不能将其用于\define可能需要在\cnsame构造内部展开的任何事物。(注意:ConTeXt 调用\protected原语\unexpanded,而我坚持使用原语名称。)

值得注意的是,这种行为是故意的:“用户命令”通常最好受到“保护”,因为有些地方缺乏扩展是完全正确的做法。

相关内容