expl3 - Is it safe to apply f/o/e-type-expansion to argument in situations where the argument in question might be empty?

Is it safe to apply f-type-expansion or o-type-expansion or e-type-expansion to a macro-argument in situations where the argument in question might be empty or where expansion of the argument in question at some stage of expansion might yield emptiness?

I ask this question because expl3.pdf, for example, seems not to address these cases.

In expl3.pdf the following is explained for f-type-expansion:

f Expanding the first token recursively in a braced token list.
Almost the same as the x type except here the token list is expanded fully until the first unexpandable token is found and the rest is left unchanged. Note that if this function finds a space at the beginning of the argument it gobbles it and does not expand the next token.

(Seems to be s.th. like \romannumeral\^^@ where things get expanded during the course of removing one optional space that might trail the alphabetic constant.)
This explanation is based on the precondition that both there is a first token in the argument and that expansion at some stage yields a non-expandable token. If the argument is empty or recursively expanding the first token at some stage yields emptiness, this precondition is not fulfilled. Cases in which this precondition is not fulfilled are not discussed in this explanation.

In expl3.pdf the following is explained for o-type-expansion:

o One-level-expanded token or braced token list.
This means that the argument is expanded one level, as by \expandafter, and the expansion is passed to the function as a braced token list. Note that if the original argument is a braced token list then only the first token in that list is expanded.
In general, using V should be preferred to using o for simple variable retrieval.

This explanation is based on the precondition that the argument has a first token. If the argument is empty, this precondition is not fulfilled. Cases in which this precondition is not fulfilled are not discussed in this explanation.

In expl3.pdf the following is explained for e-type-expansion:

e Fully-expanded token or braced token list which does not require doubled # tokens. This expansions is very similar to x-type but may be nested and does not require that # tokens are doubled.

Here it is not assumed that the argument contains tokens at all. So emptiness of the argument should not be a problem. But to be on the safe side I included this case in my question anyway.

The following tests seem to work out flawlessly, but I didn't find a definite statement in interface3.pdf/expl3.pdf/etc. Probably I overlooked it.

\documentclass{article}
\newcommand\test[1]{\par\noindent The argument is between parentheses: (\detokenize{#1})}
\begin{document}
\ExplSyntaxOn
\exp_args:Nf\test{}
\exp_args:Nf\test{\empty}
\exp_args:Nf\test{\csname empty\endcsname}
\exp_args:Ne\test{}
\exp_args:Ne\test{\empty}
\exp_args:Ne\test{\csname empty\endcsname}
\exp_args:No\test{}
\ExplSyntaxOff
\end{document}

• Coming across this question, note that the documentation explicitly states that \exp_last_unbraced:Nf might be unsafe. The "normal" kinds are safe (but some of these might secretly be implemented using that one...?). Jun 27 at 12:55
• @user202729 interface3.pdf says in the section "3expan" - "unbraced expansion" that with some of the \exp_last_unbraced:N...-functions braces are stripped from the last argument before performing the expansion denoted by the argument-type of the last argument and that this may lead to problems in case the argument in question is empty. Somehow the concept "expanding for getting arguments in line as the result of expansion" is mixed with the concept "having arguments expanded that already are in line". I think you cannot ensure to one hundred percent separation of these two concepts. Jun 27 at 14:04

1 Answer

All of these argument specifiers (e, o, f, x) will work correctly with an empty brace group. This is true even for f-type expansion as an argument can be grabbed, so there is a closing brace in all cases. We document that o` can be applied to a single unbraced token, but the other argument types do not have this (documented) ability.