0

I find expansion in LaTeX really confusing :(.

Consider the following expl3 code:

(Note that \l_tmpa_tl and \l_tmpb_tl are set elsewhere. So I can't just say \cs_set_nopar:Nn \dcp_baz: { { xyz } { \S 6 } }. Neither can I say \cs_set_nopar:Nn \dcp_baz: { { \l_tmpa_tl } { \l_tmpb_tl } }. I need it expanded. But I don't want it exhaustively expanded. I just want to recover what's in the variables \l_tmpa_tl and \l_tmpb_tl.)

\documentclass{article}
\usepackage[T1]{fontenc}
\ExplSyntaxOn
\cs_new_nopar:Nn \dcp_foo:
  {
    \tl_set:Nn \l_tmpa_tl { xyz }
    \tl_set:Nn \l_tmpb_tl { \S 6 }
    \exp_args:NVV \dcp_bar:nn \l_tmpa_tl \l_tmpb_tl
    \dcp_baz:
  }
\cs_new_nopar:Nn \dcp_bar:nn
  {
    \cs_set_nopar:Nn \dcp_baz: { {#1} {#2} }
  }
\cs_set_eq:NN \Foo \dcp_foo:
\ExplSyntaxOff
\begin{document}
\Foo
\end{document}

This does what I want, in that \dcp_baz: ends up being a macro containing {xyz}{\S 6}.

However, I have two questions:

  1. Can I do this in expl3 without the helper function \dcp_bar:nn?
  2. How would I do this in LaTeX2e?
3
  • what is "this" though here? as your top level \foo/dcp_foo: doesn't take arguments your two tmp macros aren't really needed, then you wouldn't need the helper to expand them and the answer to (2) would be \newcommand\Foo{\def\dcpBaz{{xyz}{\S 6}}} \Foo but is that the answer you need? Jul 3, 2021 at 12:24
  • @DavidCarlisle, sigh always wanting clarity :). xyz and \S 6 are in macros that are set elsewhere. Jul 3, 2021 at 12:28
  • that;s what I suspected, would have been clearer to set them outside the macro probably but anyway I posted an answer to 2, I'll see if I can think of the correct idom for 1 Jul 3, 2021 at 12:33

1 Answer 1

1

A couple of versions for 2 then 1

\documentclass{article}

\begin{document}

\newcommand\FooA{\def\dcpBaz{{xyz}{\S 6}}}
\FooA \show\dcpBaz

\newcommand\FooB{%
  \def\tmpa{xyz}%
  \def\tmpb{\S 6}%
  \edef\dcpBaz{%
     {\unexpanded\expandafter{\tmpa}}{\unexpanded\expandafter{\tmpb}}}}
    \FooB \show\dcpBaz

in a pure expl3 universe \verb|\S| would be etex protected not via `\verb|\protect|`
so

\protected\def\newS{\S}


\ExplSyntaxOn
\cs_new_nopar:Nn \dcp_foo:
  {
    \tl_set:Nn \l_tmpa_tl { xyz }
    \tl_set:Nn \l_tmpb_tl { \newS 6 }
    \cs_set_nopar:Nx \dcp_baz: { {\l_tmpa_tl} {\l_tmpb_tl} }
    \show\dcp_baz:
  }
\cs_set_eq:NN \FooC \dcp_foo:
\ExplSyntaxOff

\FooC
\end{document}

7
  • Yes! I think \FooB is the kind of thing I'm after. I was using \edef without the \unexpanded\expandafter. This is what I mean when I say that i find expansion confusing. I don't actually really understand your answer :). Jul 3, 2021 at 12:36
  • @DavidPurton expl3 version being added Jul 3, 2021 at 12:41
  • 1
    @DavidPurton the \expandafter expands the \tmpb then the \unexpanded stops any further expansion, eg of \S. Jul 3, 2021 at 12:42
  • 1
    @DavidPurton well that depends, if you leave \S defined as \protect\Sspace then you will need a helper function or directly write the \fooB version just using the expl3 renamed versions of \unexpanded and \expandafter . You wouldn't need that if the macros being used were defined by expl3 commands as they are either safe to expand or etex \protected. so the idiomatic expl3 way is as I show here but it doesn't work for \S as that isn't defined by expl3. It's the price you pay for having expl3 not a clean start latex3 without the 2e compatibility issues. Jul 3, 2021 at 12:55
  • 1
    @DavidPurton yes more or less the intention of the :neXVnnn argument specifiers are that you don't need the chains of \expandafter that you classically need, and just writing \expandafter as \exp_after:wN isn't really an improvement, but here (unless I missed something) you need something like that or your helper version as in the question. Jul 3, 2021 at 13:03

You must log in to answer this question.

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