6

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? – Joseph Wright May 27 '14 at 10:14
  • 1
    Note that (currently) the team feel that testing for 'emptiness' is more of a 'code level' than 'interface level' thing. – Joseph Wright May 27 '14 at 10:20
  • I hope the new example helps to set the context. – Andy May 27 '14 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}] } }. – Bruno Le Floch May 27 '14 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 '14 at 14:27
5

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}

which leads to

! Missing number, treated as zero.
<to be read again> 
                   \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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.