38

The following code

\def\foo#1#2\baz{\#1: -#1- \quad \#2: -#2-}

1) \foo hello world\baz

2) \foo supercalifragilistiexpialidocious\baz

3) \foo a \baz

4) \foo a\baz

%5) \foo \baz % error!

\bye

yields

enter image description here

The cases 1) to 3) are perfectly understandable to me. To a certain surprise, even 4) works: the second argument #2 becomes empty (and the two hyphens render as an en dash). But then case 5) breaks down with Runaway argument? ! Paragraph ended before \foo was complete instead of recognizing both arguments as empty.

I wouldn't have bothered if also case 4) had broken down: both cases 4) and 5) failing would seem "logical" to me. Or I'd expect both of them to work. Alas, my logic is seldom trustworthy :-)

0

2 Answers 2

31

From \def\foo#1#2\baz{..}, the #1#2 bit means that #1 is not delimited, so it's either a single token or a braced argument, so the commands grabs a single token or a braced group (the only way one of this arguments are empty is with {}); after that, the #2\baz part means that #2 is indeed delimited, so it grabs until \baz (removing possibly outer braces, this can be empty by just putting \baz next). In case 4 it grabs first argument, and then goes until \baz for the second one; in case 5 it grabs first argument (which is \baz) and then grabs until \baz but there is no \baz left (it's been grabbed as first argument) so it cannot grab the second argument, hence the error message.

Maybe it could help to think in terms of nested commands, each grabbing one argument. \def\foo#1#2\baz{(1:#1) and (2:#2)} could be done like

\def\foo#1{(1:#1) and \footwo}
\def\footwo#1\baz{(2:#1)}
2
  • Thanks to your cues I found the relevant description in the TeXBook p. 203f. Reading it first would spare me embarrassing questions :-)
    – campa
    Commented Jun 28, 2018 at 12:38
  • 18
    @campa no, the TeXBook is written such that you need to understand how tex works first then read the book to understand what it was telling you:-) Commented Jun 28, 2018 at 12:41
25
+50

Introduction to the topic

Chapter 24: Summary of Vertical Mode of the TeXbook, the chapter where TeX's parts of speech are defined in a modified form of the Backus-Naur-notation, indicates that the pattern for defining macros by means of primitives \def, \gdef, \edef, \xdef is:

prefixes\def|\gdef|\edef|\xdefcontrol sequence⟩⟨parameter text⟩⟨left brace⟩⟨balanced text⟩⟨right brace

prefixes⟩ either is empty or is a combination of some or of all of the primitives\global/​\outer/​\long/​\protected.

control sequence⟩ is a control word token or a control symbol token or an active character token.

left brace⟩ is an explicit character token of category 1 (begin group).
right brace⟩ is an explicit character token of category 2 (end group).

In Chapter 20: Definitions (also called Macros) of the TeXbook the ⟨balanced text⟩ is also referred to as ⟨replacement text⟩.

parameter text⟩ contains no ⟨left brace⟩ and no ⟨right brace⟩ and there can be as many as nine parameters, #1 to #9, which must be numbered in order. # stands for any explicit character token of category 6 (parameter). At the time of defining macros, parameters in the ⟨parameter text⟩ can be delimited in quite a general way by placing tokens behind them.

Only parameters introduced in the ⟨parameter text⟩ may occur in the ⟨replacement text⟩.

Providing parameters at the time of defining a macro implies that at the time of expanding an instance of the macro in question and delivering the replacement text TeX for each parameter gathers a set of tokens from the token stream and within the ⟨replacement text⟩ replaces the corresponding parameter by the corresponding set of tokens.

A set of tokens gathered for replacing a parameter of a ⟨replacement text⟩ is called an argument/a macro argument.
Thus the ⟨parameter text⟩ of a macro definition can be seen as a pattern which is to be obeyed by TeX at the time of expanding instances of the macro in question when gathering from the token stream sets of tokens forming that instance's arguments.

At the time of defining a macro you can have ⟨parameter text⟩ and parameters.
At the time of expanding an instance of a macro it is about macro arguments.

If in the ⟨parameter text⟩ of a macro's ⟨definition⟩ a parameter is delimited, then at the time of expanding an instance of that macro, the corresponding macro argument, whose tokens are to be gathered from the token stream, is delimited also, by the set of tokens which in the ⟨parameter text⟩ forms the delimiter of the corresponding parameter.

Subtlety:

In this answer "⟨replacement text⟩" (with "⟨" and "⟩") denotes the ⟨balanced text⟩ at the time of defining a macro. ⟨replacement text⟩ may contain parameters #1, #2, ..., #9 that are introduced in the ⟨parameter text⟩.
In this answer "replacement text" (without "⟨" and "⟩") denotes the tokens which you get at the time of expanding an instance of a macro. In "replacement text" parameters are replaced by the tokens that form the corresponding macro arguments.

The focus of this answer is not on providing ⟨parameter text⟩ when defining macros.

The focus of this answer is on how at the time of expanding instances of macros TeX gathers sets tokens from the token stream that are to form macro arguments.

Can \outer tokens occur in ⟨parameter text⟩?
Can \outer tokens be components of macro arguments?

Tokens that are \outer cannot be part of a ⟨parameter text⟩.

\outer tokens also cannot be components of macro arguments.

\outer tokens can make it into the ⟨replacement text⟩ of macro definitions by means of the \edef...\noexpand-trick :

\outer\def\foo{This is foo and foo is outer.}
\edef\bar{%
  This is bar and it calls 
  {\noexpand\tt\noexpand\string\noexpand\foo:}
  \noexpand\foo
}

\foo

\bar

%This would yield an error:
% ! Forbidden control sequence found while scanning definition of ... 
%\def\bar{This is bar and it calls {\tt\string\foo:} \foo}

\bye

enter image description here

About \long and short

In case a macro is defined in terms of \long, such as \long\def\macro#1#2{...}, all arguments of instances of that macro can contain the token \par.
A macro defined in terms of \long colloquially is called a "long macro".

In case a macro is not defined in terms of \long, such as \def\macro#1#2{...}, if with one of its instances an argument contains the token \par, this triggers an error message on the console/terminal in terms of a question about "Runaway argument?"

E.g., something like the following console-output:

*\def\macro#1#2{Argument 1: #1; Argument 2: #2}

*\macro{\par argument 1}{argument 2}
Runaway argument?
{
! Paragraph ended before \macro was complete.
<to be read again> 
                   \par 
<*> \macro{\par
                argument 1}{argument 2}
? 

Unlike the \long-prefix, there is no \short-prefix. Nonetheless, a macro not defined in terms of \long is sometimes colloquially called a "short macro".

The \long mechanism detects the token \par no matter if \par has its usual meaning (as something that "tells" TeX that the end of the paragraph is reached and that TeX shall typeset that paragraph) or if \par is redefined. The \long-mechanism does not detect tokens other than \par whose meaning equals that of the \par-primitive.

E.g., after

\let\pur=\par 
\def\par{Hello!}

the \long-mechanism still takes \par as a trigger for the runaway-argument-message while \pur is not a trigger for the runaway-argument-message.

About the order in time in which TeX does gather macro arguments

When expanding an instance of a macro, TeX takes the ⟨parameter text⟩ from the corresponding ⟨definition⟩ for the directive to gather the macro arguments one by one from the token stream.

For example, with a definition

\def\macro#1#2\DelimiterOne#3#4\DelimiterTwo\DelimiterTwo{%
  ⟨replacement text where parameters #1/#2/#3/#4 may occur⟩%
}

the ⟨parameter text⟩ is: #1#2\DelimiterOne#3#4\DelimiterTwo\DelimiterTwo.

The parameter #1 is not delimited.
The parameter #2 is delimited by the token \DelmiterOne.
The parameter #3 is not delimited.
The parameter #4 is delimited by the tokens \DelmiterTwo\DelimiterTwo.

Thus at the time of expanding an instance of \macro TeX first gathers from the token-stream a set of tokens according to the rules for gathering an undelimited argument. That set of tokens is the first argument of this instance of \macro. When delivering the replacement text, TeX replaces the parameter #1 of \macro's ⟨replacement text⟩ by the set of tokens forming the first argument of this instance of \macro.
Then TeX gathers from the token-stream a set of tokens according to the rules for gathering a delimited argument whereby the delimiter is formed by the token \DelimiterOne. That set of tokens is the second argument of this instance of \macro. When delivering the replacement text, TeX replaces the parameter #2 of \macro's ⟨replacement text⟩ by the set of tokens forming the second argument of this instance of \macro.
Then TeX gathers from the token-stream a set of tokens according to the rules for gathering an undelimited argument. That set of tokens is the third argument of this instance of \macro. When delivering the replacement text, TeX replaces the parameter #3 of \macro's ⟨replacement text⟩ by the set of tokens forming the third argument of this instance of \macro.
Then TeX gathers from the token-stream a set of tokens according to the rules for gathering a delimited argument whereby the delimiter is formed by the tokens \DelimiterTwo\DelimiterTwo. That set of tokens is the fourth argument of this instance of \macro. When delivering the replacement text, TeX replaces the parameter #4 of \macro's ⟨replacement text⟩ by the set of tokens forming the fourth argument of this instance of \macro.

There are two sorts of macro arguments:

1. Undelimited macro arguments

Undelimited macro arguments are indicated by undelimited parameters in the ⟨parameter text⟩. An undelimited parameter is a parameter whereafter either the ⟨left bracet⟩ enclosing the ⟨replacement text⟩ or another parameter follows.

There are two possibilities what a set of tokens forming an undelimited argument can look like:

  • A single token which neither is an explicit character token of category 1(begin group) nor is an explicit character token of category 2(end group). That is, a single token which neither is an opening curly brace {1, nor is a closing curly brace }2.
    Henceforth such a thing is called a not-enclosed undelimited argument.

  • A set of tokens enclosed in a leading explicit character token of category 1(begin group) and a trailing explicit character token of category 2(end group), and containing explicit character tokens of category 1(begin group) and explicit character tokens of category 2(end group) in a way where each explicit character token of category 1(begin group) has exactly one matching explicit character token of category 2(end group) and vice versa. That is, it is a set of tokens enclosed in an opening curly brace and a closing curly brace, and if there are more curly braces within, then each opening curly brace has exactly one matching closing curly brace and each closing curly brace has exactly one matching opening curly brace.
    Henceforth such a thing is called an enclosed undelimited argument.

Using this terminology you can say: Enclosed undelimited arguments consist of stuff that forms the enclosing and of stuff which is enclosed. (The set of tokens forming stuff which is enclosed may be empty.)

At the time of expanding a macro the tokens forming the replacement text of that macro are delivered. Hereby undelimited parameters (#1 or #2 or...) occurring in the ⟨replacement text⟩ are replaced as follows:

In case the undelimited parameter happens to be a not-enclosed undelimited argument, the parameter is replaced by the token forming that not-enclosed undelimited argument.

In case the undelimited parameter happens to be an enclosed undelimited argument, the parameter is replaced by the tokens that form the enclosed stuff of the enclosed undelimited argument, while the explicit character token of category 1(begin group) and the explicit character token of category 2(end group) forming the enclosing are discarded/removed/stripped off.

If a macro passes an argument to another macro, something like

\def\foo#1{\bar#1!}
\def\bar#1{\string\bar's argument is in parentheses: (#1)}

, where the exclamation mark indicates the place of the last token of the argument of \foo and parentheses surround what is processed as argument of \bar, then each macro might remove a level of surrounding curly braces:

  • \foo{{Argument}} yields \bar{Argument}!, which in turn yields \string\bar's argument is in parentheses: (Argument)!.

  • \foo{{A}rgument} yields \bar{A}rgument!, which in turn yields \string\bar's argument is in parentheses: (A)rgument!.

  • \foo{Argument} yields \bar Argument!, which in turn yields \string\bar's argument is in parentheses: (A)rgument!.

When TeX starts gathering an undelimited macro argument from the token stream, it silently discards explicit space tokens (i.e., explicit character tokens of category 10(space) and character code 32), until finding a token that is not an explicit space token.

That token may be something other than an explicit character token of category 1(begin group) or 2(end group) and thus form a not-enclosed undelimited macro argument.

That token may as well be an explicit character token of category 1(begin group) and thus form the left side of the enclosing of an enclosed undelimited macro argument.

This discarding of explicit space tokens is the reason why having spaces between/right before undelimited macro arguments and not having spaces between/right before undelimited macro arguments makes no difference:

\def\ProcessTwoNonDelimitedArgs#1#2{Arg1:(#1), Arg2:(#2)}

% A <space token> between {Argument1} and {Argument2}:
\ProcessTwoNonDelimitedArgs{Argument1}  {Argument2}

% No <space token> between {Argument1} and {Argument2}:
\ProcessTwoNonDelimitedArgs{Argument1}{Argument2}
\bye

enter image description here

2. Delimited macro arguments

Delimited macro arguments are indicated by delimited parameters in the ⟨parameter text⟩. A delimited parameter is a parameter whereafter in the ⟨parameter text⟩ a set of tokens follows neither containing explicit character tokens of category 1(begin group), nor containing explicit character tokens of category 2(end group), nor containing explicit character tokens of category 6(parameter). Such a set of tokens is called the delimiter of the parameter.

A delimited macro argument is a macro argument which is delimited by an instance of the set of tokens which in the ⟨parameter text⟩ of the ⟨definition⟩ of the macro forms the delimiter of the corresponding parameter.

I.e., a delimited macro argument is delimited by a set of tokens containing neither opening curly braces, closing curly braces, nor explicit hashes.

(#6, hash, is an explicit character token of category 6(parameter). Examples of implicit character tokens of category 6(parameter) are the implicit hash-character-tokens of category 6(parameter) \hash and U with \let\hash=# or \catcode`\U=13 \letU=#. The #-doubling at times of unexpanded writing etc only occurs with explicit character tokens of category 6(parameter).)

With delimited parameters the delimiting set of tokens is always right behind the parameter. With delimited macro arguments the delimiting set of tokens is always right behind the macro argument.

Argument delimiters can contain implicit character tokens of category 6(parameter) if the tokens constituting the implicit character tokens of category 6(parameter) were not yet implicit character tokens of category 6(parameter) when defining took place, but were turned into implicit character tokens of category 6(parameter) by redefining them afterwards.

\let\ImplicitHash=# %
\def\Macro#1\ImplicitHash\ImplicitHash#2\ImplicitHash{Arg1:(#1), Arg2:(#2)}
\Macro{A1}\ImplicitHash\ImplicitHash{A2}\ImplicitHash
\bye

does not work, while

\def\Macro#1\ImplicitHash\ImplicitHash#2\ImplicitHash{Arg1:(#1), Arg2:(#2)}
\let\ImplicitHash=# %
\Macro{A1}\ImplicitHash\ImplicitHash{A2}\ImplicitHash
\bye

enter image description here

does work.

When TeX gathers a delimited macro argument for a macro, tokens are gathered from the token stream until

  • either tokens are found that form the matching argument delimiter,
  • or it is obvious that an error message needs to be raised.

At the time of gathering tokens of a delimited macro argument, a sequence of tokens which looks like those tokens that within the ⟨parameter text⟩ of the corresponding macro definition form the argument delimiter, is only considered the argument-delimiter if it occurs within the same brace-group as the macro token where the delimited argument in question belongs to.

I.e.: suppose there is a sequence of tokens in the token stream which at first looks like the tokens that form the argument delimiter within the ⟨parameter text⟩ of the macro definition. However, these tokens are not within the same curly-brace-group as the macro token whose macro arguments are gathered. As a result, TeX does not take this token sequence for the matching argument delimiter.

Taking such a sequence for a matching argument delimiter would imply the possibility of delimited macro arguments where explicit character tokens of category 1(begin group) or 2(end group) don't have matching counterparts (i.e. where curly braces don't have matching counterparts).

Therefore, proper curly-brace-nesting/proper balancing of explicit character tokens of category 1(begin group) with matching explicit character tokens of category 2(end group) is taken into account when searching an argument delimiter.

For instance, after defining

\def\macro#1\deli\miter{This is the argument: (#1)}

calling \macro as in

\macro PartOfArgument{\deli\miter}OtherPartOfArgument\deli\miter

yields that #1 from the ⟨parameter text⟩ of the definition with this call is considered a placeholder for

PartOfArgument{\deli\miter}OtherPartOfArgument

.

In cases of finding the matching argument delimiter, the tokens forming the argument delimiter are discarded. After finding and discarding the matching argument delimiter, TeX checks whether the entire set of tokens gathered for the macro argument so far (that set can be empty in case the delimiter is found immediately) is enclosed in a leading explicit character token of category 1(begin group), and a trailing explicit character token of category 2(end group). I.e., after finding and discarding the matching argument delimiter, TeX checks whether the entire set of tokens gathered for the macro argument so far is enclosed in curly brace tokens. If so, these two tokens are removed. (This can result in emptiness in case TeX only gathered an explicit character token of category 1(begin group) followed by an explicit character token of category 2(end group) when finding the delimiter—that is, if TeX gathered only a pair of matching curly braces before finding the delimiter.)

There are situations where you wish to avoid this removal of the outermost level of curly braces from delimited macro arguments. This can easily be achieved by putting a token in front of the actual argument which cannot accidentally/erroneously match the argument delimiter and at the end of the expansion-chain having this token removed.

E.g.:
(\detokenize in use, thus eTeX-extensions required this time ;-) )

\def\DoNothing{}%
\def\RemoveDot.{}%
\def\macro#1#2\delimited{\detokenize\expandafter{#1#2}}%

\tt

% Stripping of curly braces with the delimited argument will take place.
% #2 will be: 'Delimited Argument'
\macro{\DoNothing}{Delimited Argument}\delimited

% Due to the leading dot, stripping of curly braces with the delimited argument will not take place.
% #2 will be: '.{Delimited Argument}'    
\macro{\RemoveDot}.{Delimited Argument}\delimited
\bye

enter image description here

When TeX starts gathering a delimited macro argument, it does not discard whatsoever token. It does not discard space tokens. When TeX starts gathering a delimited macro argument, anything that might be taken for a preceding space token is part of the set of tokens that forms the macro argument.

Let's exhibit these subtleties:

Assume denotes a space and \macro is defined as follows while LaTeX2e with eTeX-extensions is in use:

\def\macro#1#2\delimited{%
  Undelimited argument: \expandafter\verb\scantokens{*|#1|};
  Delimited argument: \expandafter\verb\scantokens{*|#2|}%
}%

When calling \macro{Undelimited}Delimited\delimited, at the delimited argument there is no ⟨space token⟩ and there are no surrounding curly braces, thus you get:

      Undelimited argument: Undelimited; Delimited argument: Delimited

When calling \macro{Undelimited}␣Delimited\delimited, at the delimited argument there is a ⟨space token⟩ and there are no surrounding curly braces, thus you get:

      Undelimited argument: Undelimited; Delimited argument: ␣Delimited

When calling \macro{Undelimited}{Delimited}\delimited, at the delimited argument there is no ⟨space token⟩ and there are surrounding curly braces—the surrounding curly braces are removed, thus you get:

      Undelimited argument: Undelimited; Delimited argument: Delimited

When calling \macro{Undelimited}␣{Delimited}\delimited, at the delimited argument there is a ⟨space token⟩ and there are curly braces. This time they do not surround the entire delimited argument because the ⟨space token⟩ is there too. Thus this time they are not removed:

      Undelimited argument: Undelimited; Delimited argument: ␣{Delimited}

There is a subtle thing in TeX: #{-notation:

When via \def giving the definition of a macro, the ⟨replacement text⟩ must be enclosed in an explicit character token of category 1(begin group) and an explicit character token of category 2(end group). I.e., when via \def giving the definition of a macro, the ⟨replacement text⟩ must be enclosed in curly braces.

Therefore you can write:

\def\macro{replacement text}
{\tt \meaning\macro}
\bye

enter image description here

When via \def giving the definition of a macro, as a special case the last token of the ⟨parameter text⟩ can be a single character token of category 6(parameter), be it explicit, e.g., a hash (#6), or implicit. If this is the case, then the explicit character token of category 1(begin group) forming the left side of the enclosing of the ⟨replacement text⟩ is also considered the last token of the delimiter of the last macro argument. Usually, when gathering tokens that are to form a delimited macro argument, the tokens forming the argument-delimiter are discarded. But in this special case, that last token of the argument delimiter of the last macro argument is not just discarded but is discarded and re-inserted, which is the same as if it would be left in place, and after expanding the macro in question that token occurs right behind the replacement text.

In the TeXbook it is explained that you can use this #{-feature for having the last macro argument of some macro delimited by an opening curly brace that is left in place so that it can, e.g., serve as opening curly brace/as the left side of the enclosing of a subsequent enclosed undelimited macro argument which in turn is to be gathered when expanding another macro token which is to come into being in the course of the expansion-cascade.

Example:

\tolerance 9999
\emergencystretch 3em
\hfuzz 0pt \vfuzz \hfuzz
\parindent=0ex
%-------------------------------------------------------------------------------------------------
\let\ImplicitHash=#
\def\macroA#1#2\relax#{Argument1:(#1), Argument2:(#2) The meaning of the next token: \meaning}
\def\macroB#1#2\relax\ImplicitHash{Argument1:(#1), Argument2:(#2) The meaning of the next token: \meaning}
\def\Weird{Whatsoever}

\tt\frenchspacing

\meaning\macroA

\noindent\hrulefill\null

\macroA{Arg 1}{Arg 2}\relax{ The meaning of the next token: \meaning}

\noindent\hrulefill\null

\meaning\macroB

\noindent\hrulefill\null

\macroB{Arg 1}{Arg 2}\relax{ The meaning of the next token: \meaning}

\bye

enter image description here

Until TeX, version 3.141592653, January 2021, there was an edge thing

(It was brought to my attention by others in the usenet newsgroup comp.text.tex in 2009. See, e.g., the usenet-discussion "Is there any difference between { } and bgroup and egroup ?")

When via \def giving the definition of a macro, as a special case the last token of the ⟨parameter text⟩ can be a single character token of category 6(parameter), be it explicit, e.g., a hash (#6), or implicit. In that special case you are not bound to the left side of the enclosing of the ⟨replacement text⟩ being an explicit character token of category 1(begin group). In that special case the left side of the enclosing of the ⟨replacement text⟩ may also be an implicit character token of category 1(begin group). After expanding the macro in question, the token denoting the implicit character token of category 1(begin group) occurs right behind the replacement text in the same way in which an explicit character token of category 1(begin group) would occur right behind the replacement text if the left side of the enclosing of the replacement text of the macro had been an explicit character token of category 1(begin group).

This is the case even if the token, which at the time of defining the macro in question denotes the implicit character token of category 1(begin group) gets redefined after defining the macro in question.

Example:

\let\Weird={
\let\ImplicitHash=#
\def\macroA#1#2\relax#\Weird Argument1:(#1), Argument2:(#2)\string}
\def\macroB#1#2\relax\ImplicitHash\Weird Argument1:(#1), Argument2:(#2)\string}
\def\Weird{Whatsoever}

\tt
\meaning\macroA

\macroA{Arg 1}{Arg 2}\relax\Weird

\meaning\macroB

\macroB{Arg 1}{Arg 2}\relax\Weird

\bye

enter image description here

The most important things to keep in mind about TeX's gathering of macro arguments are:

  1. TeX gathers macro arguments from the token stream one by one.

  2. In case of gathering a delimited macro argument, TeX gathers tokens from the token stream until finding the delimiter. This implies that delimited macro arguments can be empty in case TeX has not yet gathered any token when finding the delimiter.

  3. When gathering undelimited macro arguments, TeX discards preceding explicit space tokens.

  4. When gathering delimited macro arguments, TeX does not discard explicit space tokens. With delimited macro arguments anything that might be taken for a preceding explicit space token is part of the set of tokens that forms the macro argument.

  5. If present, one level of curly braces surrounding an entire macro argument, be it a delimited macro argument or an undelimited macro argument, is discarded/removed/stripped off.

With your definition

\def\foo#1#2\baz{\#1: -#1- \quad \#2: -#2-}

TeX at the time of expanding \foo in any case first gathers an undelimited macro argument and then gathers a delimited macro argument where \baz is the delimiter:

  1. \foo hello world\baz

    At the time of expanding \foo TeX gathers the tokens of the undelimited macro argument, discarding preceding space tokens if present, and then discarding curly braces surrounding the entire macro argument if present:
    h

    Then TeX obtains the delimited macro argument by gathering tokens until finding the delimiter \baz and then—if present—discarding curly braces surrounding the entire set of tokens gathered so far:
    ello world

  2. \foo supercalifragilistiexpialidocious\baz

    At the time of expanding \foo TeX gathers the tokens of the undelimited macro argument, discarding preceding space tokens if present, and then discarding curly braces surrounding the entire macro argument if present:
    s

    Then TeX obtains the delimited macro argument by gathering tokens until finding the delimiter \baz and then—if present—discarding curly braces surrounding the entire set of tokens gathered so far:
    upercalifragilistiexpialidocious

  3. \foo a \baz

    At the time of expanding \foo TeX gathers the tokens of the undelimited macro argument, discarding preceding space tokens if present, and then discarding curly braces surrounding the entire macro argument if present:
    a

    Then TeX obtains the delimited macro argument by gathering tokens until finding the delimiter \baz and then—if present—discarding curly braces surrounding the entire set of tokens gathered so far: As space tokens do get removed only when they are preceding undelimited macro arguments while this is a delimited macro argument, the ⟨space token⟩ between the a and the \baz-delimiter will be gathered as the macro argument.

  4. \foo a\baz

    At the time of expanding \foo TeX gathers the tokens of the undelimited macro argument, discarding preceding space tokens if present, and then discarding curly braces surrounding the entire macro argument if present:
    a

    Then TeX obtains the delimited macro argument by gathering tokens until finding the delimiter \baz and then—if present—discarding curly braces surrounding the entire set of tokens gathered so far: In this case the delimiter is found immediately, while not yet having gathered any tokens. Thus in this case the macro argument is empty.

11
  • What could be the use-cases of \def\macro#1#\bgroup Argument1:(#1)\string} and why does \let\implicithash# \def\macro#1\implicithash{} not work?
    – Manuel
    Commented Jul 2, 2018 at 14:18
  • Ok, after playing a bit, \def\macroa#\bgroup\hbox} is exactly the same (\ifx sense) as \def\macrob\bgroup{\hbox\bgroup}. Plus \let\implicithash# lets you use \implicithash as you would use # in macro definitions, but not in second level... weird.
    – Manuel
    Commented Jul 2, 2018 at 14:30
  • @Manuel The question was not about use cases but about how things work. Somethings knowing about subtleties not needed for the use-case is both funny and helpful for finding out about subtleties that might disturb the use-case. \let\implicithash# \def\macro#1\implicithash{} does work as it is one of the very special cases explained in the section There is one edge thing. In this comment I don't have enough characters left for explaining how it works. Thus I will do that in the next comment. Commented Jul 2, 2018 at 14:40
  • @Manuel: \let\implicithash# \def\macro#1\implicithash{} will eat tokens until the next opening-brace. E.g., \let\implicithash# \def\macro#1\implicithash{} \def\putinparentheses#1{(#1)} \expandafter\putinparentheses\macro This is to be eaten{This is to be in parentheses} \bye Commented Jul 2, 2018 at 14:41
  • 1
    You ever think making an article for tugboat (or Die TeXnische Komödie) out of this?
    – campa
    Commented Feb 27, 2021 at 18:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .