28

Is there a real difference between

\newcount\acounter
\def\dosomething{\afterassignment\dosomesecret\acounter=}
\def\dosomesecret{I do something with \the\acounter}

and

\newcount\acounter
\def\dosomething#1{\acounter=#1%
    I do something with \the\acounter}

What is the plus of \afterassignment? Why should I prefer one solution over the other?

2 Answers 2

34

The main difference is that using \afterassignment you can preserve the assignment syntax. So in your counter example any number of tokens following \dosomething would be expanded until a sequence of non expandable tokens making a <number> are scanned. The second version forces a macro-argument syntax where the number has to be given as a single token or brace group. Which is preferable depends on what you are trying to do.

Another example from the latex sources

\def\protected@edef{%
   \let\@@protect\protect
   \let\protect\@unexpandable@protect
   \afterassignment\restore@protect
   \edef
}

\protected@edef takes the syntax of \edef with delimited arguments etc and restores the meaning of \protect after the \edef. So you can do

\protectected@edef\foo#1#2\@nil{.....#1...#2}

It would be rather less convenient to do that without using \afterassignment.

Another, perhaps better, example again based on usage in the latex base, the following plain TeX file

\def\removetonil#1\xx{}

\def\myset#1{\afterassignment\removetonil
             \dimen0=#1pt\relax\xx
             \immediate\write20{[\the\dimen0]}}

\myset{3}
\myset{3em}    
\myset{3cm}
\myset{\vsize}

\bye

Produces

[3.0pt]
[30.00005pt]
[85.35826pt]
[643.20255pt]

This is setting \dimen0 to a user-specified length where the argument may omit the units (defaulting to pt) or give explicit units, or be a TeX dimen register or primitive such as \vsize. By using \afterassignment the primitive assignment may or may not use tokens after #1 pt\relax will be used if the argument is a <number> but not if it is already a dimension. Because \removetonil is inserted immediately after the assignment it can clear away any unused tokens.

11

The \afterassignment macro exposes TeX's lexing routines to the user. As David pointed it out in his answer, this can simplify the processing of macro arguments. You can also build on this to elaborate lexers or parsers in plain TeX.

I wrote the geoptk package for plain TeX, which allows to define macros taking arguments as TeX primitives \hbox, \hfill and so on do. Using this package, you can define a macro \begindisplay that you can call like

\begindisplay file {chapter1} literal offset 20pt

This input text is replaced by

\display@M{%
    \getoptk@behaviour@display@file{chapter1}%
    \getoptk@behaviour@display@literal
    \getoptk@behaviour@display@dimen{20pt}%
}

so that \display@M can do its job and trigger the behaviours at the appropriate time.

The lexing routine involved heavily relies on \afterassignment. The package code is short enough, so that you can “get it” in a couple of hours and I also wrote an article in TUGBoat about this.

http://www.ctan.org/pkg/getoptk

http://tug.org/TUGboat/tb32-2/

5
  • in the example, can one switch the order of things after \begindisplay: \begindisplay offset 20pt file {chapter1}?
    – user4686
    Oct 20, 2013 at 9:12
  • Of course you can! :-) Oct 20, 2013 at 9:14
  • ... great :) (@zuié to make it 15 characters)
    – user4686
    Oct 20, 2013 at 9:16
  • 1
    @MichaelGrünewald: I just had a quick look at your package. There seems to be a typo in the documentation: you use 'dimen' where you mean 'offset'. This also carried over to your answer. :-)
    – mhelvens
    Oct 20, 2013 at 9:25
  • @mhelvens I admit, I copy and edited the example from the documentation of the package. :) I will fix this, thank you for pointing it out! Oct 20, 2013 at 9:27

You must log in to answer this question.

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