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.

Knuth hid a special rule for delimited arguments in exercise 20.5 of the TeXbook.

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.

This means that a macro can be defined as,

\def\a#1#{#1}

calling it as \a 10 will give a runaway argument error whereas calling it as \a{12}, will compile with no trouble.

I struggled to find a practical application for such macros even after looking at TeX by Topic, TeXbook and LaTeX source.

Here is my take on it, create some commands to typeset and do some calculations for fractions, as for example those found in basic arithmetic texbooks. You type this,

\[\FRAC ADD{3}{8}+{1}{7}\]
\[\FRAC SUB{5}{8}-{1}{7}\]
\[\FRAC MUL{5}{8}x{13}{1201}\]

and you get this:

enter image description here

Here is the code,

\documentclass{article} 
\begin{document}
%% macro factory
\def\FRAC#1#{\csname #1\endcsname}
%% add
\def\ADD#1#2+#3#4{%
  \frac{#1}{#2}+\frac{#3}{#4}=
  \frac{\the\numexpr(#4*#1)+(#3*#2)}{\the\numexpr#2*#4}
}
%% subtract
\def\SUB#1#2-#3#4{%ok top
  \frac{#1}{#2}-\frac{#3}{#4}=
  \frac{\the\numexpr(#4*#1)-(#3*#2)}{\the\numexpr(#2*#4)}
}
%% multiply
\def\MUL#1#2x#3#4{%
  \frac{#1}{#2}\times\frac{#3}{#4}=
  \frac{\the\numexpr(#1*#3)}
  {\the\numexpr#2*#4}
}
%% testing
\[\FRAC ADD{3}{8}+{1}{7}\]
\[\FRAC SUB{5}{8}-{1}{7}\]
\[\FRAC MUL{5}{8}x{13}{1201}\]
\end{document}

Are there any practical applications for such macros? Are there any special precautions one should take? Why would Knuth include this facility in the first place?

share|improve this question
    
This is an older question, but here's a recent answer that uses this technique: tex.stackexchange.com/questions/85033/colored-symbols –  Scott H. Dec 9 '12 at 19:08
    
@ScottH. Heiko magic:) thanks for the pointer. Feel free to edit my question and add the link in somehow, it can be very useful for reference. –  Yiannis Lazarides Dec 9 '12 at 19:49

6 Answers 6

up vote 15 down vote accepted

This trick of catching until the first open brace can be used in many situations.

  • As other posters said, it allows to catch an optional argument expandably if it is not the last. It is possible in principle to get this to be fully robust with respect to nesting, but not implemented yet.

  • It can be used to parse the body of a definition provided by the user, to change it to fit your purposes while keeping a natural syntax. (More on parsing def below.)

  • I've used this trick primarily to parse a token list expandably without losing any brace. For instance,

    • to expandably uppercase or lowercase a given string (see this answer)

    • to fully expand a token list expandably (almost as well as the luatex primitive \expanded (see this answer)

    • to expand tokens selectively, or in the reverse order

    • to write a primitive macro expander (i.e. take a file, and expand user-defined macros)

    so basically any situation where you need to be careful with braces, but cannot use \futurelet.

This trick only works if there is only one character with catcode 1 (begin group character). Also, we need to be able to put a sentinel at the end of the token list that we are manipulating: otherwise, in the absence of opening brace, we would get a runaway argument.

On parsing a definition: say that you want to give the user an easy way of defining a macro which possibly takes arguments, and always produces a boxed math result. Say that you also want the parameter text to be arbitrary. Either you let the user do everything, or you parse the definition using the trick you ask about.

%non-user-friendly
\def\foo_#1^#2#3#4{\fbox{$\sum_{#1}^{#2} \frac{#3}{#4}$}}

%more user friendly (perhaps)
\boxeddef\foo_#1^#2#3#4{\sum_{#1}^{#2} \frac{#3}{#4}}

To do that:

\documentclass{article}
\makeatletter
\def\boxeddef#1#2#{\boxeddef@aux{#1}{#2}}
\def\boxeddef@aux#1#2#3{\def#1#2{\fbox{$#3$}}}
\makeatother
\begin{document}
%\def\foo#1#2#3#4{\fbox{$\sum_{#1}^{#2} \frac{#3}{#4}$}}
\boxeddef\foo_#1^#2#3#4{\sum_{#1}^{#2} \frac{#3}{#4}}
\[
\foo_{a}^{b}{C}{D}
\]
\end{document}
share|improve this answer

an example from latex.ltx

\def\usepackage#1#{%
  \@latex@error
    {\noexpand \usepackage before \string\documentclass}%
    {\noexpand \usepackage may only appear in the document
      preamble, i.e.,\MessageBreak
      between \noexpand\documentclass and
      \string\begin{document}.}%
  \@gobble}

with the argument setting you can handle optional arguments, eg \usepackage[foo]{bar} without defining the different cases

share|improve this answer

The #{ trick can allow to make macros which behave somewhat like \hbox{...}, in the sense that they can have, for example, verbatim inside their argument (also, the argument is not read beforehand). There’s a nice example in the Tugboat article The TeX Hierarchy (Volume 15, 1994, p. 7-9):

Programming style comparison

Compared to the Wizard’s version, the Guru’s use of #{ makes sure that the character eaten by \let\next= will always be a brace, never something else.

share|improve this answer
1  
@Philippe: Just to make sure I'm getting it: the \let\next= just serves the purpose to eat the opening { of \bold{...}, correct? –  Hendrik Vogt Mar 14 '11 at 22:22
1  
@Hendrik: yes, and the \bgroup is here to match the closing brace of \bold{...}. –  Philippe Goutet Mar 14 '11 at 22:28
    
@Philippe: What about making the command behave like \toks assignments, which expand whatever lies between them and a begin-group token? \def\bold{\expandafter\boldaux\romannumeral-\0}` and \def\boldaux#{\bgroup\bf\let\next= } Also, using a \futurelet test might be better if we want \bold a to work. –  Bruno Le Floch Mar 14 '11 at 22:38
1  
I wonder what is happening with: \def\bold#{\bgroup\bf\let\next= }\halign{\bold{#}\crcr test}\bye. –  morbusg Aug 24 '12 at 16:51
1  
@morbusg: Nice catch. From tracing things up, it seems that the \cr is seen before the end brace, but I don't know enough about the inner workings of \halign to tell you more (although \def\bold#{\bgroup\bf\let\next= }\halign{\bold{{#}}\cr test\cr}\bye does work). You should ask a new question about this. –  Philippe Goutet Aug 24 '12 at 20:22

Reading everything up the opening { as argument like \def\A#1#{...} would do, it is not very common, but useful when you want to read optional arguments of macro which normal argument must start with { anyway. This can be very useful in cases when the macro should be fully expandable and therefore \futurelet (used by \@ifnextchar) can't be used.

Funnily, I just started to use this TeX feature this week: In my up-coming package 'filemod' I define expandable and non-expandable macros to read and compare file modification dates. The expandable implementation of \filemodNewest takes an optional argument and list of file names {{filename1}{filename2}...{filename3}} and expands the the name of the newest file. The #{ syntax is used to read the potential optional argument (a number in this case):

\def\filemodNewest#1#{%
  \expandafter\expandafter
  \expandafter\@filemodNewest
  \csname
    @%
  \ifx\@nnil#1\@nnil
    first%
  \else
    second%
  \fi
    oftwo%
  \endcsname
    {[\filemodcmpdefault]}%
    {#1}%
}

It should be noted that this works only for simple optional arguments which do not include braces. This excludes e.g. complex PGF keys etc.

Also the etextools defines another way of expandable macros with optional arguments using eTeX \detokenize.

share|improve this answer
    
it is possible to extend this expandable parsing of optional arguments in a fully robust way, as long as the last argument is a brace group (assuming that there is only one character with catcode 1). That's on my todo list for Joseph's xparse. –  Bruno Le Floch Mar 13 '11 at 21:21
    
@Reader: If you find the use of \csname ... \endcsname funny, have a look at the rest of the code where \csname is used to recursive expand parts of the compare loop :-) –  Martin Scharrer Mar 13 '11 at 21:24
    
@Bruno: xparse is not mine: I just revisited the code from stuff others had written! (See also my comments about the limitation of { and on trailing optional arguments: I suspect \futurelet is the only truly robust approach, but am happy to be proved wrong.) –  Joseph Wright Mar 13 '11 at 21:47
    
@Joseph: After studying TeX's mouth for a while, I believe that you are right on this. The current xparse chokes in some cases with optional argumentsdelimited by implicit characters. More on this by email. –  Bruno Le Floch Mar 14 '11 at 22:41

I just used this construction in my expandable sanitizer: Can one define an expandable command that removes control sequences from its argument?. The purpose there is so that I can parse some arbitrary (well-formed) input for the first group it contains, without actually entering the group. Without \futurelet or \catcode changes, it's impossible to grab a single brace token, but this way, I can expand up until a group, leaving the braces there, and then continue processing with the sure knowledge that the next thing on the menu is a group. It has exactly the same purpose as \futurelet for this one token.

share|improve this answer
    
I read your answer in the post you quote. It's an amazing piece of code. –  Yiannis Lazarides Nov 9 '11 at 8:09
    
@Yiannis: Thanks so much! –  Ryan Reich Nov 9 '11 at 8:13

I use this possibility in the next case. I can't use delimiters like () because the parenthesis are nested. With

\documentclass{minimal}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc} 

\def\macro#1#{%
  <#1>\par
  \macrobis
}
\def\macrobis#1{and <#1>}

\begin{document}
\macro(exp(1),ln(2)){A}
\end{document}

The first #1 catches (exp(1),ln(2))

enter image description here

share|improve this answer
    
As I recently got told here xparse is able to parse () or [] arguments in an way so that they can be properly nested. But for simpler macros this way is much faster. –  Martin Scharrer Mar 13 '11 at 21:32
    
@Martin Yes I know and you are right. The method is more direct and much faster like you said. My english language is poor so I have some difficulties to explain exactly how useful is this method. –  Alain Matthes Mar 13 '11 at 21:41
    
@Martin: One issue with the # method is that it only works for whatever token was catcode 1 at definition time. Not a problem for almost all applications, but if we get xparse right as part of LaTeX3 then this is something that might be important. It's also no good for something that requires the last argument is optional (for example \break). –  Joseph Wright Mar 13 '11 at 21:46

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.