5

This is a followup to the question Are \def and \define the same in ConTeXt?

This snippet of code in mkiv ConTeXt (TeX Live 2013 version):

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

gives the following output, including an error:

...
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

However if we change the \define at the beginning to \def, the error goes away. The answer at https://tex.stackexchange.com/a/55778/6973, while helpful, only seems to describe the differences in terms of arguments to macros. In this case, where there are no arguments, why does \switchtobodyfont[\smallfontsize] fail when \smallfontsize is defined using \define? We would like to understand this better so we can avoid using \define in unsafe ways in the future.

A secondary question would be this (teach a man to fish!)... When confronted with the above error messages, we were at a loss to figure out what the problem was. The diagnostics didn't seem to point toward what the problem was, in a way we could understand. (It gave us the right line number, but the actual \switchtobodyfont[\smallfontsize] was buried a couple of macro invocations deep, along with a lot of other code.) We only figured out a solution because a colleague did a lot of trial-and-error commenting out code to find the offending line, and because we had run into a similar problem a long time ago. Is there something in that output that we can learn to interpret so that we could infer the cause and the solution of the problem? (Or could the diagnostic messages be improved to give a better clue to the cause?)

  • \define creates \unexpanded macros that interfere with the parser. Also, the \{setup,switchto}bodyfont macros are known to have some quirks: wiki.contextgarden.net/… – Philipp Gesang Nov 13 '13 at 16:28
  • @phg: ok. I've been reading that wiki page section (which sounds like the title of a Charles Willams novel), but the quirk described there, namely the limitation that only integer sizes are reliable, doesn't seem to apply to this case. I don't understand how to tell that \switchtobodyfont needs to expand content and something else doesn't. But maybe I just need to avoid \define. – LarsH Nov 13 '13 at 16:33
3

The \def primitve creates expandable macros, or at least ones that will expand inside an \edef or \csname. On the other hand, \define uses \protected\def to create a protected macro. These don't expand inside \csname, and so are not suitable for use in anything that needs to expand content in this way. As such, you can't use \define for anything which might need to expand inside a \cnsame construct. (Note: ConTeXt calls the \protected primitive \unexpanded, while I'm sticking to the primitive names.)

It's worth noting that this behaviour is deliberate: 'user commands' often are best made 'protected' as there are places where the lack of expansion is entirely the right thing to do.

  • Thanks, this is very helpful. Can you give an example of when lack of expansion is the right thing to do? I think that will help me understand the contrast with \switchtobodyfont[...], which requires the content to be expanded. – LarsH Nov 13 '13 at 16:38
  • Can you point me to a reference for the \protected primitive? I don't see it at tug.org/utilities/plain/cseq.html#p-ai – LarsH Nov 13 '13 at 22:32
  • 2
    @LarsH \protected (or it’s Context alias \unexpanded) is described in the ε-TeX manual (p. 14 of the PDF version, see also the reference). – Philipp Gesang Nov 14 '13 at 10:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.