Is a latex3 function without a (hollow) star expandable

latex3

In interface3.pdf sec 1.2, it says the function with a star can be fully expandable in x, e, f, and the function with a hollow star can be fully exandable in x and e, and cannot be fully expanded within an f-type argument. My first question is

How deeply will f-type argument expand the "hollow star"

enter image description here

And my main question: there are also some funtion without star, like \tl_set_eq:NN, how will x, e, f-type arguments regard it? I made some test and the output confused me.

\documentclass{article}
\begin{document}
\ExplSyntaxOn
    \tl_new:N \l_tmpc_tl
    \tl_new:N \l_tmpd_tl
    \tl_set:Nn \l_tmpa_tl { abc }
    \tl_set:Nn \l_tmpb_tl { ABC }
    % I want to reset \l_tmpb_tl the same as \l_tmpa_tl, and set \l_tmpc_tl (\l_tmpd_tl)  
    \tl_set:Nf \l_tmpc_tl { \tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl \l_tmpb_tl }
    \tl_set:Nx \l_tmpd_tl { \tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl \l_tmpb_tl }
    \tl_show:N \l_tmpc_tl
    \tl_show:N \l_tmpd_tl
\ExplSyntaxOff
\end{document}

After compiling with pdflatex, it output:

> \l_tmpc_tl=\tex_let:D \l_tmpb_tl = \l_tmpa_tl \l_tmpb_tl .
<recently read> }

l.11     \tl_show:N \l_tmpc_tl

?
> \l_tmpd_tl=\tl_set_eq:NN ABCabcABC.
<recently read> }

l.12     \tl_show:N \l_tmpd_tl

?

We can see that f-type expanded \tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl into a tex primitive:

\tex_let:D \l_tmpb_tl = \l_tmpa_tl \l_tmpb_tl

However x-type didn't do things on \tl_set_eq:NN, it just left it in the output stream. ~~Why would this happen?~~ And how does latex3 expand a no-star-function?


UPDATE:

Countinuing reading interface3.pdf, I found it in sec 4.3:

Functions which are not “protected” are fully expanded inside an x expansion. In contrast, “protected” functions are not expanded within x expansions.

And I reached back to the definition of \tl_set_eq:NN, it is "protected"

> \tl_set_eq:NN=\protected\long macro:#1#2->\tex_let:D #1= #2.
<recently read> }

l.13     \cs_show:N \tl_set_eq:NN

So it can't be expanded by x-type argument, and protected function can be expanded by f-type. Am I right here?

And then my second question becomes: Are all functions without a star protected?

Best Answer

Yes, all functions without a star are (or at least should be) \protected, this way they don't expand on x or e type expansion or when written to a file.

f and c type expansion are a different and ignore \protected. But it is wrong to (intentionally) expand them (the functions without stars) with f-type expansion.

f-type expansion will expand everything until it hits the first unexpandable token (as already said ignoring \protected, so this means until it hits either an unexpandable primitive or a character token of categories 1, 2, 3, 4, 6, 7, 8, 11, or 12) or a space (the space would then be gobbled, the unexpandable token would stay there).

By the way, many of the hollow-starred functions aren't necessarily f-type safe, but could be, this depends on the user code being supplied. For instance \int_step_function:nN is not f-expansion safe, but a usage such as \int_step_function:nN {10} \use_none:n would be (though admittedly this is a nonsense example). The reason for this (the fact they are marked with a hollow star) is usually because they iterate over some input and for each element leave some code in the input stream, and that code could be unexpandable or not whatever, so there is no guarantee that it would always work out.

Related Question