4

As pointed out by the following MCE, \TeX and \LaTeX are expl3-written to an auxiliary file:

  • the same way when no manipulation is involved (\iow_now:Nn) (but that is useless for my real use case):

    \LaTeX {}
    \TeX {}
    
  • differently when exhaustive expansion is involved (\iow_now:Nx):

    \protect \LaTeX  {}
    T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@{}
    

Why this difference and how to get \protect \TeX {} instead of T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@{}?

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\iow_new:N \g_output_stream

\iow_open:Nn \g_output_stream { \c_sys_jobname_str.sbj }
\iow_now:Nn \g_output_stream { \LaTeX{} }
\iow_now:Nn \g_output_stream { \TeX{} }
\iow_now:Nx \g_output_stream { \exp_not:V\LaTeX{} }
\iow_now:Nx \g_output_stream { \exp_not:V\TeX{} }
\iow_close:N \g_output_stream

\ExplSyntaxOff

\begin{document}
\end{document}
Denis Bitouzé
  • 9,652
  • 4
  • 27
  • 85

2 Answers2

5

You don't want \exp_not:V, but rather \exp_not:N

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\iow_new:N \g_output_stream

\iow_open:Nn \g_output_stream { \c_sys_jobname_str.sbj }
\iow_now:Nn \g_output_stream { \LaTeX{} }
\iow_now:Nn \g_output_stream { \TeX{} }
\iow_now:Nx \g_output_stream { \exp_not:N \LaTeX{} }
\iow_now:Nx \g_output_stream { \exp_not:N \TeX{} }
\iow_close:N \g_output_stream

\ExplSyntaxOff

\begin{document}
\end{document}

The auxiliary file will have

\LaTeX {}
\TeX {}
\LaTeX {}
\TeX {}

What's the difference? In this case \exp_not:V does a one step expansion, which is not desired here, because \LaTeX and \TeX are not variables, but parameterless functions. Recall that V stands for variable and is used to get its value, not subject to further expansion.

egreg
  • 1,121,712
  • I should have mentioned that what is written to the auxiliary file is in fact (only) the replacement text (that may contain \TeX) of a token list. Hence, if I'm right, \exp_not:N is useless in my use case: I asked this new question in order to explain why and a bit further my aim. – Denis Bitouzé May 10 '19 at 14:50
4

If we do \show\TeX, the result is

\TeX=macro:
->T\kern -.1667em\lower .5ex\hbox {E}\kern -.125emX\@.

On the other hand, the result of \show\LaTeX is

   > \LaTeX=macro:
   ->\protect \LaTeX  .

Now \LaTeX is defined in latex.ltx using \DeclareRobustCommand, and as @egreg has pointed out, \MakeRobust can protect an existing macro in the same way.

\documentclass{article}
\MakeRobust{\TeX}

\usepackage{xparse}

\ExplSyntaxOn

\iow_new:N \g_output_stream

\iow_open:Nn \g_output_stream { \c_sys_jobname_str.sbj }
\iow_now:Nn \g_output_stream { \LaTeX{} }
\iow_now:Nn \g_output_stream { \TeX{} }
\iow_now:Nx \g_output_stream { \exp_not:V\LaTeX{} }
\iow_now:Nx \g_output_stream { \exp_not:V\TeX{} }
\iow_close:N \g_output_stream

\ExplSyntaxOff

\begin{document}
\end{document}
Ian Thompson
  • 43,767