Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In How to create a macro with two or three ;-separated arguments?, Herbert uses a macro definition

\def\defpoint#1#{\expandafter\defpoint@i#1;;\@nil}

which Joseph Wright reports as having a "grab to #{" argument. How does this work? Where is it useful? Are there any restrictions? Does it extend in the same way nested macro definitions would? As in, using ##{ if redefining a macro within another one.

share|improve this question
4  
By rule, each ## pair in a replacement text is changed into a single # when the macro is expanded. –  egreg Dec 29 '11 at 0:36
2  
Please see tex.stackexchange.com/questions/13333/…, there is a good discussion. This question needs to be rephrased otherwise is duplicate. –  Yiannis Lazarides Dec 29 '11 at 8:58
    
have a look into the LaTeX kernel latex.ltx. Search for #{ and you'll find all the places where it is used and will easily understand the meaning, eg \documentclass[...]{...} for grabbing the [...], –  Herbert Dec 29 '11 at 10:33
    
Related Question: What does \def\foo#{…} mean?. –  Peter Grill Apr 12 at 2:54
add comment

2 Answers 2

up vote 13 down vote accepted

What does it mean?

To repeat the factual information that Martin gave: defining a macro like

\def\macro<other arguments>#{<replacement text>}

accomplishes the functional equivalent of trying to write

\def\macro<other arguments>{{<replacement text>{}

except that it works, because the above breaks two rules of macro definitions. First, it can't function as intended because TeX, when scanning a \def, will read until the first { to find the arguments, and once it reaches that brace, will assume that the replacement text has started. So you can never actually have { in the arguments. And second, while scanning the replacement text, it will skip over balanced brace-pairs, so the opening { you try to insert will prevent it from stopping its absorption of the replacement text at the following }. (You can get around this one by using \bgroup, but the first problem is unsolvable without #{.) So this syntax really covers the one logical case of delimited arguments that is excluded by these parsing rules.

To answer your last question, yes, you can write

\def\bigmacro{
  \def\macro##{<stuff>}
  <more stuff>
}

so that when calling \bigmacro, it begins by defining \macro to have a "delimited brace" after it. As egreg and Martin have said, doubling the # is just part of TeX's syntax.

Why does it work that way?

Okay, there's a more general situation that's excluded by the rules, namely, the putative

\def\macro<args>{<more args>{<replacement>}

where you want to match a { right in the middle of the arguments. You can't do that with #{. I don't know for sure, but it is consistent with the way things work that this is so that no part of TeX's argument scanning in macro expansion will destroy brace pairs. You see, as it currently stands, #{ will use an opening brace as a boundary for argument grabbing, but will not include it in the grabbing, because it is put back after being found. This means that a group {...} remains intact.

If you think about how the rules work, this always happens in unrestricted scanning. You can destroy a group with \let, but that's because you are saying "look for the next token"; it's not possible to write \let\a={<stuff>}; or rather, it would result in \let\a={ followed by <stuff>} (and so probably an error). But with macro argument scanning, TeX just looks until it finds something to call #1, and since the rules allow using {...} to form a "group" that can be caught, it's important not to cross the boundaries of brace pairs. Someone might have written them intentionally to signal to the argument scanner.

Another reason not to break brace groups is, of course, that if you write

{\macro <stuff> {<more stuff>} ...

and if \macro could somehow catch the opening {, then <stuff> and <more stuff> would end up in the same group, perhaps against the expectations of whomever wrote it. That would cause some problems with \aftergroup, at least. (I admit that this is an incredibly technical point, but then, so is #{.)

When is this construction useful?

Sanitizing

Well, I found it useful in this answer of mine. The question was how to expandably convert TeX code into "plain text", roughly, and I needed to use only macro expansion to find groups in that code so I could remove them (and also so I could work around their effects in inhibiting my own code). So part of my sanitizer is a macro defined like

\def\SanitizeGroups#1#{

the effect of which is that I know that #1 is everything between the appearance of \SanitizeGroups and the first following group. In other words, #1 contains no groups and right after it there is a group. That means that if I use a macro like

\def\SanitizeTokens#1{...}

to parse individual "tokens" of the text following \SanitizeGroups, I can be sure that everything picked up by a call to \SanitizeTokens is actually a single token and not, say, something inside {...}.

Verbatim arguments

Another use: in this answer to a question about the #{ construction, Philippe Goutet presents an example from a Tugboat article:

\def\bold#{\bgroup\bf\let\next= }

which means that \bold will simply "insert \bf at the beginning of the immediately-following group"; the purpose of #{ here is to make sure that when you use \let to swallow the opening brace of that group, it really does swallow a brace. This forces the user to write \bold{<text>} rather than, possibly, \bold a to get a single bold letter a, but then, you have to use braces with \bf anyway so it's not much of an imposition. The reason for doing it this way rather than

\def\bold#1{{\bf #1}}

(the "Programmer" approach, only the third level of TeXpertise out of seven in that article) is that if you don't read the stuff in the braces, its catcodes are not fixed, so it can contain verbatim text.

share|improve this answer
    
I have an issue with \def\bold#{\bgroup\bf\let\next= }. What happens if I do \expandafter\bold\@spaces{x}, or if space is active? The reason for doing it this way, rather than \def\bold#1{{\bf #1}}, is that if you don't read the stuff in the braces, its catcodes are not fixed, so it can contain verbatim text. What happens in, eg, \footnote? –  Ahmed Musa Dec 29 '11 at 10:54
    
@AhmedMusa: if you use \expandafter\bold\space{x}, you're going to get an error, and that's perfectly normal as you're not using \bold as it should be used (nothing is allowed between \bold and the brace). I don't understand what you mean about \footnote: you won't be able to put verbatim inside it whether you're using \bold or not. –  Philippe Goutet Dec 29 '11 at 11:39
    
@ Philippe I can put verbatim material in footnote. But what I meant was that when dealing with, say, footnote, the token \def\bold#{\bgroup\bf\let\next= } will be read long before \bold is encountered, thereby disagreeing with the highlighted statement of Ryan. The other point is that \def\bold#{\bgroup\bf\let\next= } can't used when blank space is active. –  Ahmed Musa Dec 30 '11 at 1:53
    
@Ahmed: First, active spaces have nothing to do with this. The only space intervening in \bold is the one after =, but that one is tokenized at definition, so as long as you are careful to set the catcode to the expected one it will not matter whether spaces are active when \bold is expanded. Second, I don't understand your objection regarding footnotes. What "token" in \def\bold#{...} is read before \bold is encountered, and why does that matter? The only concern is that the "argument" of \bold shouldn't be tokenized before \bold is expanded. –  Ryan Reich Dec 30 '11 at 2:21
    
@Ahmed: no, you can’t put verbatim material in footnotes (try in a minimal document and see: not even \footnote{\verb"a"} will work). That is, unless you’re using a package which specifically does this (e.g. fancyvrb with \VerbatimFootnotes). But something like \textbf{\footnote{\verb"%"}} or \footnote{\textbf{\verb"%"}} will fail. But both \bold{\footnote{\verb"%"}} and \footnote{\bold{\verb"%"}} will work fine if verbatim is allowed in \footnote. That's because of Ryan’s statement. –  Philippe Goutet Dec 30 '11 at 7:54
add comment

When a macro's parameter text ends with a # direct before the {, then the { is taken as part of the parameter text and is also appended to the replacement text. This means with \def\foo#1#{..}, \foo will read everything till the next { as the first argument, but insert the { back to input stream afterwards. Therefore You can't use such a macro to remove a { character. Also the macro must have at least one normal (mandatory) argument which is enclosed in { }. If the macro is defined without any argument, i.e. \def\foo#{..}, it will await a { directly after its usage. However spaces will be removed as usually. In any other case the macro acts the same as any other macro.

This is explained in The TeXBook on page 215, directly after Exercise 20.5.

Such macros are sometimes used to implement macro with optional arguments. For example the color and xcolor packages define \textcolor to grab everything before the next { and pass it to an internal macro as first argument, which then checks if it is empty. This is an expandable alternative to \futurelet or \@ifnextchar, but requires that braces are used for the mandatory argument. This leads sometimes to issues because some people like to drop the braces around single token arguments.

If such a macro is (re-)defined inside another one the # must be doubled as normal, i.e. \def\bar{\def\foo##1##{..}}. The doubling of # is, AFAIK, independent from the actual local purpose of the #, so there is no difference here.

share|improve this answer
    
It only works with the character specified, so 'any catcode one character' will not work. –  Joseph Wright Dec 29 '11 at 8:21
    
@JosephWright: Thanks, I removed it. I wasn't sure about it, anyway. –  Martin Scharrer Dec 29 '11 at 8:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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