11

Is there a way to get something like

\test
\newcommand{\test}{Print me!}

to work in the same manner as

\newcommand{\test}{Print me!}
\test

would work? Basically I'm wondering if I can set a macro or a predefined value in something that executes in a compile phase and then displays properly if I use it before its defined in the LaTeX file.

Thanks for your help!

  • 3
    Welcome to TeX.SX!. No, it's impossible this way. But you can use the .aux file for the macro \test have the desired value at the next run of LaTeX. Can you please be some more specific about your need? – egreg Jun 1 '15 at 21:00
7

TeX is like a one-way street when it starts compiling. So you'll have to use alternative means (including alternative macro usages) to achieve what you're after.

Below the command \laterdef acts like a "\label" which writes a global (re)definition to the .aux immediately. First compilation yields abc for \test while subsequent compilations output def:

\documentclass{article}

\providecommand{\test}{abc}% Create \test to be abc

\makeatletter
\newcommand{\laterdef}[2]{%
  \protected@write\@auxout{}{\gdef\string#1{#2}}}
\makeatother

\begin{document}

\test

\laterdef{\test}{def}% Overwrite \test to be def

\end{document}

The .aux is read in as part of \begin{document}. So, any redefinition of \test between \begin{document} and \test will nullify the use of \laterdef.

Without \providecommand{\test}, you'll receive an error during the first compile.

  • 1
    What if #2 contains fragile stuff? Try \laterdef{\test}{\textbf{def}} for example... Instead of \robustifying the macro name only I'd wrap everything with \unexpanded: \immediate\write\@auxout{\unexpanded{\gdef#1{#2}}} – cgnieder Jun 2 '15 at 8:08
  • 1
    You should use \protected@write; the \robustify part is useless: just say \gdef\string#1{#2}. Since \gdef is not expandable it is written as is and \string in front of it is not needed. – egreg Jun 2 '15 at 8:47
  • 1
    Actually, \protected@write expands everything except \protected tokens (but it defers expansion of \thepage until the \shipout); also, its \write is not \immediate. – GuM Jun 2 '15 at 15:15
  • 1
    @GustavoMezzetti It's good that \protected@write is not immediate and doesn't expand \thepage. Any reference to the page number in the replacement text of \laterdef could not be trusted on. Of course, knowing better what the OP has in mind would allow better analysis. – egreg Jun 2 '15 at 16:42
  • 1
    @egreg: I didn’t say that \protected@write is not good, neither I meant it. (Anything coming from you is “good” almost by definition! ;-) I just wanted to clarify the point, given the previous reference to \unexpanded. – GuM Jun 2 '15 at 16:52
6

First of all I want to underline that LaTeX already has a mechanism for the most frequent cases when “delayed definitions” are needed. If you want to use a generated number even before the place where it's generated, or the page number where the event occurs, you just place \label{<string>} after the command that generates the number and you can print the generated number by \ref{<string>} or the page number by \pageref{<string>}.

A generated number is, for instance, a section number or the item number in an enumerate and so on.

It's not possible to use a command before it has been defined, because TeX proceeds with tokens one at a time (and macros can change their meaning any time). The mechanism above works by writing a note in the .aux file, so the “delayed item” will be known only at the next LaTeX run. This might look annoying, but no document is ever finished at the first LaTeX run, so this is really not a problem.

You can even abuse the above mechanism:

\newcounter{laterdef} % just a dummy counter
\newcommand{\laterdef}[2]{%
  \renewcommand\thelaterdef{#2}%
  \refstepcounter{laterdef}\label{#1}%
}

Here's a full example, where the text has special commands (accents here) to show that no particular protection is needed in general; some commands may need \protect in front of them (look on the site for “fragile command”).

\documentclass{article}

\newcounter{laterdef} % just a dummy counter
\newcommand{\laterdef}[2]{%
  \renewcommand\thelaterdef{#2}%
  \refstepcounter{laterdef}\label{#1}%
}

\begin{document}

This is some text where we want to
use something that will be known only
later: \ref{test}.

Here is text that follows.

Now we define the contents needed
above.

\laterdef{test}{Na\"ive Stra\ss e}

\end{document}

During the LaTeX run you may see the following messages on the console:

LaTeX Warning: Reference `test' on page 1 undefined on input line 13.

LaTeX Warning: There were undefined references.

LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

If you later change the text in \laterdef, you'll just see the last message; the first two happens when a reference is not yet known.

The first LaTeX run will produce

enter image description here

where the unknown text has been replaced by ??

The next LaTeX run will produce instead

enter image description here

If you're bold and want to define a mechanism yourself, you can:

\documentclass{article}

\makeatletter
\newcommand{\lateruse}[1]{%
  \@ifundefined{late@#1}{??}{\@nameuse{late@#1}}%
}
\newcommand\laterdef[2]{%
  \protected@write\@auxout{}{%
    \global\string\@namedef{late@#1}{#2}%
  }%
}
\makeatother

\begin{document}

This is some text where we want to
use something that will be known only
later: \lateruse{test}.

Here is text that follows.

Now we define the contents needed
above.

\laterdef{test}{Na\"ive Stra\ss e}

\end{document}
  • Why isn’t the “space hack” appropriate in this case? – GuM Jun 2 '15 at 16:39
  • @GustavoMezzetti It would require explanations and I don't think it's the best way to cope with the problem anyway. – egreg Jun 2 '15 at 16:40

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.