# Test for empty value in xparse

Following the recommendation of the answers to this question, I use the following code

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\IfNoValueOrEmptyTF}{mmm}
{
\IfNoValueTF{#1}
{#2} % true
{\tl_if_empty:nTF {#1} {#2} {#3}} % false
}
\ExplSyntaxOff


to test for either no or an empty value.

One corresponding macro is

\NewDocumentCommand \sidenotemark { o } {%
\IfNoValueOrEmptyTF{#1}%
{%...


However, I changed the code to

\NewDocumentCommand \sidenotemark { O{} } {%
\IfEmptyTF{#1}%
{%...


and

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\IfEmptyTF}{mmm}
{ \tl_if_empty:nTF {#1} {#2} {#3}
}
\ExplSyntaxOff


because I feel it is more readable.

However, it seems odd that there is neither \IfEmptyTF nor \IfNoValueOrEmptyTF in xparse.

Is there a better way to achieve the described behavior (while keeping the optional argument instead of key value pairs?).

--- UPDATE ---

It is rather hard to make an example useful and minimal. I hope this makes it clearer. In the next example I would expect the same behavior from empty and no value.

\documentclass{book}

\usepackage{xparse}
\usepackage{lipsum}
\usepackage{marginnote}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\IfNoValueOrEmptyTF}{mmm}
{
\IfNoValueTF{#1}
{#2} % true
{\tl_if_empty:nTF {#1} {#2} {#3}} % false
}
\ExplSyntaxOff

\NewDocumentCommand \placemarginal {o m}
{
\IfNoValueOrEmptyTF{#1}
{\marginpar{#2}} % is empty, use marginpar
{\marginnote{#2}[#1]} % is not empty, use marginnote
}

\begin{document}
float\placemarginal{\lipsum[1]}

float\placemarginal[]{test2}

fix\placemarginal[0pt]{test}

\end{document}

• NoValue is distinct from 'empty': that's rather the point in xparse. Can you illustrate the type of input you are expecting? May 27, 2014 at 10:14
• Note that (currently) the team feel that testing for 'emptiness' is more of a 'code level' than 'interface level' thing. May 27, 2014 at 10:20
• I hope the new example helps to set the context.
– Andy
May 27, 2014 at 10:55
• I'd expect to use \NewDocumentCommand \placemarginal { O{} m } { \marginal:nn {#1} {#2} } then \cs_new_protected:Npn \marginal:nn #1#2 { \tl_if_empty:nTF {#1} { \marginpar {#2} } { \marginnote {#2} [{#1}] } }. May 27, 2014 at 12:51
• It seems, that I crossed the ´interface level´ and reached the ´code level´ in the terms of @JosephWright. I still feel, I did not descent that far down, yet. Although, to gauge this is quite subjective I guess.
– Andy
May 27, 2014 at 14:27

Conceptually, an optional argument which is not given is not the same as one that's simply empty. Depending on the defined semantics of your interface, giving an optional argument without content may be simply wrong. A simple example is \makebox:

\documentclass{article}
\begin{document}
\makebox[]{foo}
\end{document}


! Missing number, treated as zero.
\relax


as the optional argument, if given, must be a dimension (number + units: adding just an integer fails too!). As such, testing if an argument is given is quite a different thing from testing the content of the argument.

In the example described, what is wanted is a variation in path depending on whether the argument is empty, not whether it is given. (Indeed, it actually seems that what might be wanted is a test to check that the argument is a dimension, but that is rather more complex.) Thus

\NewDocumentCommand \placemarginal {o m}
{
\IfNoValueOrEmptyTF{#1}
{\marginpar{#2}} % is empty, use marginpar
{\marginnote{#2}[#1]} % is not empty, use marginnote
}


doesn't really seem to be right: o is only sensible if a present/not present test is useful. Here, a 'LaTeX2e-like' optional makes more sense

\ExplSyntaxOn % As I'm using \tl_if_blank:nTF
\NewDocumentCommand \placemarginal {O{} m}
{
\tl_if_blank:nTF {#1}
{\marginpar{#2}} % is empty, use marginpar
{\marginnote{#2}[#1]} % is not empty, use marginnote
}


If you want to force an error before invoking \marginnote then you could go for something like

\ExplSyntaxOn % As I'm using \tl_if_blank:nTF
\NewDocumentCommand \placemarginal {O{} m}
{
\dim_compare:nNnTF { #1  + 0pt } = \c_zero_dim
{\marginpar{#2}} % is empty, use marginpar
{\marginnote{#2}[#1]} % is not empty, use marginnote
}


which will do the same as the blank test but also complain if #1 is not a dimension.