expl3
includes the o
, f
, and x
argument specifiers for one-level and the two kinds of full expansion, respectively, before passing the argument to the base function. What is the preferred way of expanding an argument twice before passing it to the base function?
As an example, I'm trying to write a l3keys
key-value interface to macros created with \DeclarePairedDelimiter
from the mathtools
package.
\tl_new:N \l__mymodule_size_tl
\keys_define:nn { mymodule }
{
size .choices:nn =
{ big , Big , bigg , Bigg }
{
\tl_set:Nn \l__mymodule_size_tl
{ [ \use:c { \tl_use:N \l_keys_choice_tl } ] }
} ,
size / auto .code:n =
\tl_set:Nn \l__mymodule_size_tl {*} ,
size / none .code:n =
\tl_clear:N \l__mymodule_size_tl
}
Usually, the size of the delimiters is passed to the macro as an optional argument of \big
etc. or *
, such as \abs[\big]{x}
where \DeclarePairedDelimiter\abs{\lvert}{\rvert}
. I would prefer to have size = big
etc. or size = auto
as a key-value interface, such as \myabs[size=big]{x}
.
The problem with the above code comes in correctly setting \l__mymodule_size_tl
in the big
etc. choices: I need to expand [ \use:c { \tl_use:N \l_keys_choice_tl } ]
twice before assigning those tokens to \l__mymodule_size_tl
.
- If I use no expansion (i.e.,
\tl_set:Nn
), the call to\abs
gets its argument in the wrong form --\l__mymodule_size_tl
will hold[ \use:c { \tl_use:N \l_keys_choice_tl } ]
, not[\big]
. - If I use one-level expansion (i.e.,
\tl_set:No
) and prepend[
after the expansion is complete,\l__mymodule_size_tl
will hold[ \cs:w \tl_use:N \l_keys_choice_tl \cs_end: ]
, not[\big]
. - If I use either
f
orx
expansion,\l__mymodule_size_tl
will hold a bunch of "garbage", not[\big]
.
What can I do? Here is an idea: Use two o
expansions, with some acrobatics between.
\tl_set:No \l__mymodule_size_tl
{ \use:c { \tl_use:N \l_keys_choice_tl } ] }
\exp_args:NNV \tl_set:No \l__mymodule_size_tl
\l__mymodule_size_tl
\tl_put_left:Nn \l__mymodule_size_tl { [ }
This is rather ugly, in my opinion. Is there anything better that I can do?
\tl_set:Nx \l__mymodule_size_tl { [ \exp_not:c { \tl_use:N \l_keys_choice_tl } ] }
?\exp_args:No \function:o {...}
which will pass double-o-expansion of{...}
to\function
. (also alluded to in Joseph Wright's answer below) -- although note that x-expansion (or the "true twice-single-expansion" of\expandafter\meaning\noexpand\empty
is different from the result of the "twice-o-expansion" above.