5

MWE:

\tl_set:Nn \l_tmpa_tl {a}
\tl_set:Nn \l_tmpb_tl {\mathbf{\l_tmpa_tl}}
\tl_set:Nn \l_tmpa_tl {b}
\(\l_tmpb_tl\)

The code snippet above actually produce \(\mathbf{b}\). What I want to achieve is to produce \(\mathbf{a}\), i.e., expand the l_tmpa_tl in the second line. However l_tmpa_tl is nested inside the \mathbf command and I do not know how to expand it. I tried

\exp_args:NNx \tl_set:Nn \l_tmpb_tl {\exp_args:Nx \mathbf{\l_tmpa_tl}}

but it doesn't work.

3 Answers 3

6

You need:

\tl_set:Nx \l_tmpb_tl { \exp_not:N \mathbf { \exp_not:V \l_tmpa_tl } }

Your approach doesn't work for two reasons. First, you can't nest x-type expansion, because x-expansion itself does not work inside x (or e) type expansion. Second, is that \exp_args:N... does not stop the function from expanding, so even after \tl_set:Nx \l_tmpb_tl { \exp_args:Ne \mathbf { ... } } (e-type expansion does work inside x- and e-type expansion), \mathbf would be expanded. What you need here is \exp_not:N to prevent expansion. Then, you can also replace \exp_args:NNx \tl_set:Nn by the simpler \tl_set:Nx, and as a matter of safety, prevent further expansion of \l_tmpa_tl by using \exp_not:V (\exp_not:V \l_tmpa_tl will expand the value of \l_tmpa_tl, and prevent further expansion).

3

In general case, just define auxiliary functions to do the work.

\tl_set:Nn \l_tmpa_tl {a}
\cs_set_protected:Npn \__tmp:n #1 {  % when this is executed, it will set \l_tmpb_tl to the desired result
    \tl_set:Nn \l_tmpb_tl {\mathbf{#1}}
}
\cs_generate_variant:Nn \__tmp:n {V}
\__tmp:V \l_tmpa_tl

Alternatively, since the operation is expandable you can do this...

\cs_set:Npn \__tmp:n #1 {  % this expands to **exp_not** of the desired result
    \exp_not:n {\mathbf{#1}}
}
\cs_generate_variant:Nn \__tmp:n {V}
\tl_set:Nx \l_tmpb_tl {\__tmp:V \l_tmpa_tl}

... which is usually more flexible/convenient.

2
  • Yes, I agree that this is quite hard to figure out by yourself & read only interface3.pdf, I add this one to my idiom list post.
    – user202729
    Apr 10 at 17:36
  • The exp_not thing is also a expl3 kind-of idiom...
    – user202729
    Apr 10 at 17:45
2

In addition to the other answers, in case you wish to get more familiar with expl3's various expansion-types:

If you want to rely on the statement of interface3.pdf that token-list-variables can be retrieved directly, i.e., without needing a \tl_use:N, within a single expansion-step, you can combine o-expansion with \exp_after:wN:

\ExplSyntaxOn
\tl_set:Nn \l_tmpa_tl {a}
\tl_set:No \l_tmpb_tl {\exp_after:wN \mathbf \exp_after:wN {\l_tmpa_tl}}
\tl_set:Nn \l_tmpa_tl {b}
%\(\l_tmpb_tl\)
\tl_show:N \l_tmpa_tl
\tl_show:N \l_tmpb_tl
%
% Neither \documenclass nor \begin{document} was used, so let's end the
% latex-run with the sledgehammer:
%
\stop

If you don't like \exp_after:wN, you can trigger f-expansion and have that stopped by an explicit space-token ~ or by an implicit space-token \exp_stop_f: which gets discarded by the f-expansion-mechanism when stopping:

\ExplSyntaxOn
\tl_set:Nn \l_tmpa_tl {a}
\tl_set:Nf \l_tmpb_tl {\exp_args:NnV \use:n {\exp_stop_f: \mathbf} \l_tmpa_tl}
\tl_set:Nn \l_tmpa_tl {b}
%\(\l_tmpb_tl\)
\tl_show:N \l_tmpa_tl
\tl_show:N \l_tmpb_tl
%
% Neither \documenclass nor \begin{document} was used, so let's end the
% latex-run with the sledgehammer:
%
\stop

If you want to make sure that things might still work out when expl3-policy reagarding direct usage of token-list-variables changes, you can combine o-expansion, \exp:w/\exp_end:-expansion and \exp_args:NnV:

\ExplSyntaxOn
\tl_set:Nn \l_tmpa_tl {a}
\tl_set:No \l_tmpb_tl {\exp:w \exp_args:NnV \use:n {\exp_end: \mathbf} \l_tmpa_tl}
\tl_set:Nn \l_tmpa_tl {b}
%\(\l_tmpb_tl\)
\tl_show:N \l_tmpa_tl
\tl_show:N \l_tmpb_tl
%
% Neither \documenclass nor \begin{document} was used, so let's end the
% latex-run with the sledgehammer:
%
\stop
2
  • 2
    Small (not really important) nitpicks: a more idiomatic way to end an f expansion is \exp_stop_f: (an implicit space token) rather than ~. Also, N and V arguments don't need braces around them (doesn't hurt either) Apr 11 at 16:01
  • @PhelypeOleinik Thanks for pointing out opportunities for improvement. I have just edited my answer to take these things to heed. :-) Apr 11 at 16:41

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.