1

Closely Related: How to implement \expandbefore, similarly to \expandafter?

In the related question, a reference is made to the "# Notation". How does the syntax work?

From an answer on the other question:

\makeatletter
%
\newcommand\name{}%
\long\def\name#1#{\UD@innername{#1}}%
%
\newcommand\UD@innername[2]{%
  \expandafter\UD@exchange\expandafter{\csname#2\endcsname}{#1}%
}%
%
\newcommand\UD@exchange[2]{#2#1}%
%
\makeatother

How does the parameter syntax, (without a number), actually work? \def\test#1#{\csname test#1\endcsname}? What are good use cases to use this pattern?

  • 2
    #1, #2, etc. are the arguments. For example, if you have \newcommand{\mycommand}[2]{#1 and #2} and \mycommand{Hello}{world} you will get "Hello and world". – user156344 Mar 3 '19 at 12:31
  • Could you highlight what you want to know? – TeXnician Mar 3 '19 at 12:38
  • In absence of the TeXbook you could have a look at §11.5.6 Brace delimiting in TeX by Topic, though the passage is not very long. – moewe Mar 3 '19 at 12:43
  • 1
    The #1# is a nice bracing trick but definitely not fundamental syntax (the usual \defs work without the second #). That's why I asked what exactly your question is. – TeXnician Mar 3 '19 at 12:45
  • 1
    See tex.stackexchange.com/a/474903/2388 for an explanation about the #1# syntax. – Ulrike Fischer Mar 3 '19 at 13:57
5

The gist of \name is:

With

\name⟨stuff without braces before the left-brace⟩{⟨stuff within braces⟩}

TeX shall as first argument fetch ⟨stuff without braces before the left-brace⟩ and as second argument process ⟨stuff within braces⟩:

The ⟨stuff within braces⟩ is taken for the name of a control-sequence-token which can be obtained via wrapping ⟨stuff within braces⟩ into \csname..\endcsname and carrying out the resulting \csname..\endcsname-expression.

Instead of {⟨stuff within braces⟩} that control-sequence-token will be behind ⟨stuff without braces before the left-brace⟩.


When macros with delimited arguments get carried out, (La)TeX gathers the tokens forming the arguments from the token-stream and hereby in the token-stream searches the argument-delimiters as the argument-delimiters are taken for markers for ending the process of gathering tokens for the argument in question.

What delimiters are to be searched is to be denoted in the ⟨parameter text⟩ of the definition.

You can denote that (La)TeX shall search as delimiter for the last argument, e.g., a \relax by writing \relax as the last thing of the ⟨parameter text⟩.

You can denote that as delimiter for the last argument (La)TeX shall search a left-brace by writing # as the last thing of the ⟨parameter text⟩.

In (almost ;-) ) any case the ⟨parameter text⟩ of a macro-definition is followed by the ⟨replacement text⟩, nested in braces.
Thus in (almost ;-) ) any case the ⟨parameter text⟩ of a macro-definition will be trailed by the left-brace of the pair of braces that surrounds the ⟨replacement text⟩.
Thus when the last token of the ⟨parameter text⟩ is a #, it will be trailed by a {.
That's why this thingie for denoting that (La)TeX shall search for a left-brace as the delimiter when gathering the last argument for the macro, is also called #{-notation.

The subtle difference with the searching for \relax and the searching for an opening-brace is:

When (La)TeX as delimiter for an argument of a macro, e.g., searches the \relax and finds it, it does not only stop gathering tokens for the argument, but it does also remove the delimiter/the \relax-token.

When (La)TeX as delimiter for the last argument of a macro searches the left-brace and finds it, it does stop gathering tokens for the last argument and it leaves that delimiter/that brace in place and puts the macro's ⟨replacement text⟩ before it.


Quotes from Prof. Donald Ervin Knuth's TeXbook, Chapter 20: Definitions (also called Macros)— Prof. Donald Ervin Knuth, professor emeritus of the art of computer programming at Stanford University, is the inventor of TeX:

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.

[...]

A special extension is allowed to these rules: If the very last character of the ⟨parameter text⟩ is #, so that this # is immediately followed by {, TeX will behave as if the { had been inserted at the right end of both the parameter text and the replacement text. For example, if you say
\def\a#1#{\hbox to #1}
, the subsequent text ‘\a3pt{x}’ will expand to ‘\hbox to 3pt{x}’, because the argument of \a is delimited by a left brace.

In other words:

If you say \def\a#1#{\hbox to #1}, the subsequent text \a3pt{x} will be processed as follows:

As argument for the macro \a TeX will from the subsequent text gather an argument which is delimited by a left-brace: It will gather the phrase 3pt.
The left-brace (and everything behind it) will be left in place while replacing \a and its argument by the ⟨replacement text⟩ yields: \hbox to 3pt so that the entire thing will be: \hbox to 3pt{x}.


In short: #{-notation (note the left-brace!) means that the last parameter of the macro in question is delimited by a left-brace (of category code 1 (begin group) ) which will be left in place when (La)TeX does gather from the token-stream the last argument for that macro.

The fact that in this special case the delimiter, i.e., the left-brace, will be left in place is noteworthy as this is the only situation where an argument-delimiter will not be removed from the token stream during the process of gathering an argument.

I.e., if the argument-delimiter would, e.g., be a \relax-token as in

\def\mymacro#1\relax{The Argument#1 was delimited by relax. }

, the \relax-token serving as delimiter would be removed when gathering the argument from the token-stream: With

\mymacro , which is nonsense,\relax...

as argument for \mymacro (La)TeX would gather from the token-stream the sequence , which is nonsense, and then it would find the token \relax and would take that \relax-token for the delimiter of the argument, and therefore (La)TeX would stop gathering tokens for the argument and it would remove the delimiter. (Then it would start gathering the other arguments of \mymacro if according to the ⟨parameter text⟩ of its definition there were any. But there are none.) Then it would deliver the ⟨replacement text⟩:

The Argument, which is nonsense, was delimited by relax. 

This ⟨replacement text⟩ would in the token stream be trailed by the three dots and therefore now the token-stream would contain:

The Argument, which is nonsense, was delimited by relax. ...

But if the definition is:

\def\mymacro#1#{The Argument#1 was delimited by a left-brace. }

and you say

\mymacro , which is nonsense,{...

, you will get

The Argument, which is nonsense, was delimited by a left-brace. {...

because unlike with the former case, where the \relax which delimits the argument gets removed, in this case, the left-brace which delimits the argument will not be removed.


The phrase

If the very last character of the ⟨parameter text⟩ is #, so that this # is immediately followed by {, TeX will behave as if the { had been inserted at the right end of both the parameter text and the replacement text.

means:

A definition usually is of pattern

\def⟨control sequence⟩⟨parameter text⟩{⟨replacement text⟩}

Assume, you wish to define a macro \macro which processes two arguments whereof the first argument is undelimited and whereof the second argument is delimited by the sequence \foo\bar and which just "spits out" the arguments.

In this case you create an expression like:

\def\macro#1#2\foo\bar{argument 1: #1 argument 2: #2}

⟨control sequence⟩ = \macro

⟨parameter text⟩ = #1#2\foo\bar

⟨replacement text⟩ = argument 1: #1 argument 2: #2

When you look at the expression, you see that at the right end of the ⟨parameter text⟩, there will be the tokens that form the delimiter of the last argument, i.e., the tokens \foo\bar. They belong to the tokens which form the ⟨parameter text⟩. Right behind them you can see the left-brace from that pair of braces that surrounds the ⟨replacement text⟩.
Thus in this case at the right end of the ⟨parameter text⟩ you find the tokens that delimit the last argument and you find the left-brace of the pair of braces that surrounds the ⟨replacement text⟩.

The sequence

\macro{A}B\foo\bar

yields:

argument 1: A argument 2: B

As you can see, the delimiting tokens \foo\bar were removed while gathering the tokens that belong to the arguments.

If instead you define:

\def\macro#1#2\foo\bar{argument 1: #1 argument 2: #2\foo\bar}

⟨control sequence⟩ = \macro

⟨parameter text⟩ = #1#2\foo\bar

⟨replacement text⟩ = argument 1: #1 argument 2: #2\foo\bar

, i.e., if you insert the delimiter \foo\bar at the right end of the ⟨replacement text⟩ also, the sequence

\macro{A}B\foo\bar

yields

argument 1: A argument 2: B\foo\bar

as if with the previous definition the delimiter had been left in place.

What if you wish to define such a thing but the delimiter not being a sequence \foo\bar but being a left-brace?

The definition should still be of pattern

\def\macro#1#2⟨delimiter⟩{argument 1: #1 argument 2: #2⟨delimiter⟩}

but for several reasons you cannot take { as ⟨delimiter⟩ and write

\def\macro#1#2{{argument 1: #1 argument 2: #2{}

and hereby take #1#2{ for the ⟨parameter text⟩ and argument 1: #1 argument 2: #2{ for the ⟨replacement text⟩:

  1. In many situations one cannot easily insert single left-braces without getting errors due to braces being unbalanced.

  2. The situation would be ambiguous because (La)TeX would have to guess whether an opening brace near/at the right end of the ⟨parameter text⟩ is an argument-delimiter or whether it belongs to that pair of braces that surrounds the ⟨replacement text⟩.
    (La)TeX would also have to guess whether the right-brace should just match the left-brace at the end of the ⟨replacement text⟩ or whether it should denote the end of the ⟨replacement text⟩.

Therefore as a syntactic workaround #{-notation was invented:

With

\def\macro#1#2#{argument 1: #1 argument 2: #2}

⟨control sequence⟩ = \macro.

⟨parameter text⟩ = #1#2#

⟨replacement text⟩ = argument 1: #1 argument 2: #2

, the ⟨parameter text⟩ does not end with a token { that shall delimit the last argument but it does end with #.

That # is used for denoting that (La)TeX shall search a left-brace as argument-delimiter when during the process of expanding \macro gathering the tokens of the last argument of \macro from the token stream. That # also denotes that the left-brace found as delimiter shall be left in place so that the ⟨replacement text⟩ of \macro goes before it.

In other words:

That # causes (La)TeX to behave as if as last token that is to delimit the last argument a left-brace was found in the ⟨parameter text⟩.

It also causes (La)TeX to behave as if the last token given in the definition's ⟨replacement text⟩ was a left-brace.


To your comment:

Umm. I don't suppose you could make something up? A best guess at what is going on? Let me rephrase, in your other example if you even have cat code 1 characters floating about in all of this. Is it right to infer that this "primitive behavior" is occurring during the input phase of reading the file? (Sorry, I am making up terminology as I go ... I am speaking of the process_input_buffer event handler.

The very first stage of processing in LaTeX is reading the input (from file or from console) and taking it for a set of instructions for putting tokens into the token-stream. (Character-tokens/control-sequence-tokens). In subsequent stages the tokens in the token-stream get processed. In an earlier one of these stages, expandable tokens, e.g., macros, get expanded. I.e., they get replaced by those tokens that form the replacement-texts of their definitions. In this stage gathering tokens for macro-arguments takes place. Thus the behavior does not take place when reading the file but does take place after reading and tokenizing, in the stage of expanding expandable tokens and hereby gathering other tokens as their arguments.


I tried to elaborate in detail on how (La)TeX does gather and process macro arguments in my answer to the question How does TeX look for delimited arguments?

I tried to elaborate in detail on \expandafter and on ways of avoiding it in my answer to the question How can I know the number of expandafters when appending to a csname macro?

I tried to elaborate in detail on the macro \name in my answer to the question Define a control sequence after that a space matters

| improve this answer | |

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.