# Can we safely use o expansion when V expansion is not available?

For example \exp_args:Nxo is available but not \exp_args:NxV. Can we safely use the former instead of the latter?

• Usually you don't need \exp_args at all but generate corresponding variants of the functions you're working with. And then you can just generate V if you need V. Feb 27 at 10:02
• No, they're different even if the result might be the same. According to the guidelines a V argument should not be braced (but the value will be), whereas an o argument should be braced. The fact that \exp_args:NxV is not predefined is of no concern, because you can do \exp_args_generate:n { xV } and then you can use \exp_args:NxV. On the other hand, generating function variants is the recommended route. Feb 27 at 10:24
• Function \cs_generate_variant:Nn (+variant ...:cn) in texdoc interface3 explains the syntax. V (and v) variant functions are usually enough in most cases. Feb 27 at 10:25
• For lowercase (o,c), the braces tells Tex where the set of tokens stops; for uppercase (V,N), no braces are needed because only one token is expected (usually the name of the variable). Feb 27 at 10:32
• @Cicada stronger than "no braces are needed" it is "braces should not be used" (although using braces does not always give an error for fficiency reasons. But in general you could end up with \def{\oops}{...} and low level tex errors if you brace N or V arguments Feb 27 at 10:55

No, they're not the same, even if in some cases they do produce the same result.

\documentclass{article}

\ExplSyntaxOn

\tl_new:N \l_jl_test_tl
\int_new:N \l_jl_test_int

\tl_set:Nn \l_jl_test_tl { tokens }
\int_set:Nn \l_jl_test_int { 42 }

\exp_args_generate:n { xV }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

\exp_args:NxV \use_ii:nn { whatever } \l_jl_test_tl

\par

\exp_args:NxV \use_ii:nn { whatever } \l_jl_test_int

\par

\exp_args:Nxo \use_ii:nn { whatever } { \l_jl_test_tl }

\par

\exp_args:Nxo \use_ii:nn { whatever } { \l_jl_test_int }

\ExplSyntaxOff

\end{document}


Do you see the problem?

You also see that if some \exp_args:N... combination is not available out of the box, you can generate it very simply.

Note that an o argument should be braced and, to the contrary, a V argument shouldn't. The fact that TeX might do the “right” thing anyway is irrelevant.

On the other hand, it is much preferable and actually recommended t avoid \exp_args:N... when it's more than a one shot case. If you feel the necessity of using \exp_args:NxV, then it's quite likely that you want to define the suitable function variant.

The question is not whether o and V are equivalent, which obviously is not the case, the question is whether one can emulate V with o. The answer is yes as suggested by the documentation interface3.pdf (p 3), but there are subtleties. The V arguments specifier gets the content of the variable, but things depend on the variable.

We can categorize variables

1. token list like variables : tl, str, seq, clist, prop, fp
2. int like variables: int, dim, skip, muskip
3. quark
4. intarray, fparray, cctab

For category 1 and 3, \foo:V <variable> is replaced by \foo:o { <variable> } For category 2, \foo:V <variable> is replaced by \foo:o { \<type>_use:N <variable> } For category 4, the variables are not suitable for a V argument.

## Demonstration for int, dim, skip, muskip

\MyTest:nn prints SUCCESS if the 2 arguments as token lists are equal, FAILURE otherwise.

% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \MyTest:nn {
\tl_if_eq:nnTF { #1 } { #2 } { SUCCESS } { FAILURE } \\
}
\cs_generate_variant:Nn \MyTest:nn { Vo }

\int_set:Nn \l_tmpa_int { 1234 }
\MyTest:Vo \l_tmpa_int { \int_use:N \l_tmpa_int }

\dim_set:Nn \l_tmpa_dim { 1234pt }
\MyTest:Vo \l_tmpa_dim { \dim_use:N \l_tmpa_dim }

\skip_set:Nn \l_tmpa_skip { 1234pt plus 1cm minus 2mm }
\MyTest:Vo \l_tmpa_skip { \skip_use:N \l_tmpa_skip }

\muskip_set:Nn \l_tmpa_muskip { 1234mu }
\MyTest:Vo \l_tmpa_muskip { \muskip_use:N \l_tmpa_muskip }
\end{document}


## Demonstration for tl, str, seq, clist, prop, fp and quarks

For \MyTest:Nn, #1 sets \My_var  to #2 and calls \MyTest:Vo with appropriate arguments.

% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \MyTest:nn {
\tl_if_eq:nnTF { #1 } { #2 } { SUCCESS } { FAILURE } \\
}
\cs_generate_variant:Nn \MyTest:nn { Vo }
\cs_new:Nn \MyTest:Nn {
#1 \My_var { #2 }
\MyTest:Vo \My_var { \My_var }
}
\MyTest:Nn \tl_set:Nn { \def\My#1{#1#1} }
\MyTest:Nn \str_set:Nn { \def\My#1{#1#1} }
\MyTest:Nn \seq_set_from_clist:Nn { \def, \My, #1, {#1#1} }
\MyTest:Nn \clist_set:Nn{ \def, \My, #1, {#1#1} }
\MyTest:Nn \prop_set_from_keyval:Nn {
\def = \My,
#1 = {#1#1},
}
\MyTest:Nn \fp_set:Nn { 3.14159 }
\quark_new:N \q_My
\MyTest:Vo \q_My { \q_My }
\end{document}


## Less contrived example

This illustrate what is possible, but this should not be used in production code because it uses unsupported features.

Here we define \foo:n to build a property list from its argument assuming it is the raw content of a property list variable and print out the items. Then we generate 'o' and 'V' variants to finally test \foo:o and \foo:V.

% !TeX program = lualatex
\documentclass{article}
\begin{document}
\noindent
\ExplSyntaxOn
\cs_new:Nn \foo:n {
\tl_set:Nn \l_tmpb_prop { #1 }
\prop_map_inline:Nn \l_tmpb_prop {
##1$\to$##2\\
}
}
\cs_generate_variant:Nn \foo:n { o, V }
\prop_set_from_keyval:Nn \l_tmpa_prop {
KEY1=VALUE1,
KEY2=VALUE2,
}
\foo:V \l_tmpa_prop
\prop_set_from_keyval:Nn \l_tmpa_prop {
key1=value1,
key2=value2,
}
\foo:o { \l_tmpa_prop }
\ExplSyntaxOff
\end{document}


## Is it safe ?

For a short time usage, it is ok, but for deployment code it is definitely not. If LaTeX internals change, this may break in the future.

• They're still not the same. Mar 2 at 16:06
• \tl_set:Nn \l_tmpb_prop is absurd. Mar 2 at 16:41
• No, o is not equivalent to V even if you use \tl_use:N. Try \ExplSyntaxOn \tl_set:Nn \l_tmpa_tl { ABCD } \tl_set:No \l_tmpb_tl { \tl_use:N \l_tmpa_tl } % should assign ABCD to tmpb \tl_set:Nn \l_tmpa_tl { DEFG } \typeout{\l_tmpb_tl} % should print ABCD, but doesn't... (and try \exp_args:No \tl_show:n { \tl_use:N \l_My_tl } to see why). Mar 2 at 16:57
• Argh, \tl_use:N is not \the !!!!!!! Mar 2 at 19:02
• @JérômeLAURENS You've discovered that seq, prop and str are macros. Mar 3 at 17:05