What is the restriction on user-defined identifiers in ConTeXt Mark IV? Should it contain Latin alphabet only? What about numbers? What about hyphen and underscores? I can't find the official rules regarding identifiers in the ConTeXt Reference Manual.

It seems to accept numbers, hyphens, and underscores, with the exception that hyphen and underscore cannot be in the very beginning of the identifier, neither can a number be in the very end. Test:

\define[0]{\My-hello-2}{Hello!} % compilation error
\define[0]{\My_hello_3}{Hello!} % compilation error
\define[0]{\_My_hello}{Hello!} % compilation error

Is this correct? I want to use the best practice.

  • 1
    Basically you can use everything you could use with \unexpanded\def in TeX. Is your question about a \unprotected context? Btw: For using best practices you will have to be a bit more specific about the kind of command you are trying to define, see the last sentences of this entry on the wiki. – TeXnician Feb 12 '19 at 14:34
  • Oh, I did not know about \unprotect! What is the difference between \def and \define? – Violapterin Feb 12 '19 at 17:41
  • @TeXnician \unprotect will not make this work because - still has catcode 12. – Henri Menke Feb 12 '19 at 20:37
  • @HenriMenke It wasn't intended to make this work. It's just that I think this question lacks some examples of use to actually recommend best practices for naming… – TeXnician Feb 12 '19 at 20:42

\def vs. \define

There are a lot of ways to define commands in ConTeXt. One of them is the good old \def primitive. The syntax is nicely described in the TeXbook:

Now that we have seen a number of examples, let's look at the precise rules that govern TeX macros. Definitions have the general form

\def〈control sequence〉〈parameter text〉{〈replacement text〉}

where the 〈parameter text〉 contains no braces, and where all occurrences of { and } in the 〈replacement text〉 are properly nested. Furthermore the # symbol has a special significance: In the 〈parameter text〉, the first appearance of # must be followed by 1, the next by 2, and so on; up to nine #'s are allowed. In the 〈replacement text〉 each # must be followed by a digit that appeared after # in the 〈parameter text〉, or else the # should be followed by another #. The latter case stands for a single # token when the macro is expanded; the former case stands for insertion of the corresponding argument. – The TeXbook, page 203.

Because it might be tedious to write things like #1#2#3#4#5 by hand if you have many arguments, ConTeXt defines a thin wrapper around \def, called \define (similar to LaTeX's \newcommand, but no support for optional arguments). The syntax is

\define[〈number of parameters〉]〈control sequence〉{〈replacement text〉}

where the 〈number of parameters〉 is optional in case it is zero. In contrast to \def, the \define macro also defines the 〈control sequence〉 as protected and emits a warning in the log, if the 〈control sequence〉 has already been defined.

Valid names

Both \def and \define have something in common and that is that the 〈control sequence〉 has to begin with an escape character (usually \) and only contain characters of category code 11 (letters) or is an active character.

The problem with \define is that it forwards whatever you give as 〈control sequence〉 directly to \def and you might end up with a different 〈parameter text〉 than you intended.

Let's take a look at your definitions:

  1. \define[0]{\My-hello}{Hello!} becomes \unexpanded\def\My-hello{Hello!} so in this case 〈control sequence〉=\My and 〈parameter text〉=-hello because - has character code 12 (other) and cannot be part of a 〈control sequence〉.

  2. As you proceed to \define[0]{\My-hello-2}{Hello!} this is turned into \unexpanded\def\My-hello-2{Hello!} again. However, \define first checks whether 〈control sequence〉 is already defined and because 〈control sequence〉=\My again, you end up with a message

    system          > command '\My-hello-2' is already defined

    in the log file. The same thing holds for \define[0]{\My_hello_3}{Hello!}.

  3. The last instance \define[0]{\_My_hello}{Hello!} is a tricky case. Above I actually lied to you when I said that a 〈control sequence〉 can only contain characters with catcode 11. There is an exception and that is when 〈control sequence〉 is a single character. The underscore has catcode 12 in ConTeXt and therefore this definition becomes \unexpanded\def\_My_hello{Hello!} where 〈control sequence〉=\_ and 〈parameter text〉=My_hello. Unfortunately, \_ is already defined (to typeset an underscore) and therefore you get the log message

    system          > command '\_My_hello' is already defined

What to do about this?

As you see it becomes quite peculiar when you want to have any special characters as part of a 〈control sequence〉. Luckily, there is a way out. TeX comes with a pair of primitives \csname...\endcsname which allows you to use characters which don't have catcode 11 as a name. Again ConTeXt comes with a handy wrapper around this:


If you want to get the 〈replacement text〉 that you stored earlier, the you can use \getvalue.

| improve this answer | |
  • When there is zero argument, are there any drawback if one always uses setvalue / getvalue in place of define? – Violapterin Feb 14 '19 at 8:56
  • 1
    @Aminopterin No. Although you might want to use \setuvalue (note the additional u) to make the definition protected (equivalent to \unexpanded\def). – Henri Menke Feb 14 '19 at 9: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.