1

What is the correct (preferred?) way to do comparisons of whether a particular token---in my examples, it's typically a single character, but it could be something like \mathcal{A} or \mathbf{b} and the like---against a macro defined with \NewDocumentCommand and friends?

Here are some examples, each of which should give me a document consisting entirely of the word 'YES' if it works as desired and 'NO' if it did not. The comparison in the examples is whether \foo expands to the letter "n" when the comparison is performed.

Example 1 (does not work):

\documentclass{minimal}
\NewDocumentCommand{\foo}{}{n}
\begin{document}
\ExplSyntaxOn
\tl_if_eq:NnTF \foo {n}
{ YES }
{ NO }
\ExplSyntaxOff
\end{document}

(note that the ExplSyntaxOn part inside \begin{document}...\end{document} is not something I would normally do; it's only there for the purposes of making a minimal example).

Example 2 (works):

\documentclass{minimal}
\newcommand*{\foo}{n}
\begin{document}
\ExplSyntaxOn
\tl_if_eq:NnTF \foo {n}
{ YES }
{ NO }
\ExplSyntaxOff
\end{document}

I have tried variations, including defining \foo with \cs_new:Npn or \cs_new_protected:Npn and variations, and those work if I do this:

\documentclass{minimal}
\ExplSyntaxOn
\cs_new:Npn \foo {n}
%\cs_new_protected:Npn \foo {n} % this works, too
\tl_new:N \l__foo_tl
\tl_set:NV \l__foo_tl \foo
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\tl_if_eq:NnTF \l__foo_tl {n}
{ YES }
{ NO }
\ExplSyntaxOff
\end{document}

However, I cannot come up with variations that make it work when \foo is defined with either \NewDocumentCommand or NewExpandableDocumentCommand.

I am certain I'm doing something wrong with the \tl_if_eq comparison, and I also know the problem traces back to how things are expanded, but I'm not certain what the "right" way to do this is for a command that is defined by \NewDocumentCommand.

3
  • 2
    'Do not do this' - or at least explain why you need to do it in the first place
    – Joseph Wright
    Oct 24, 2023 at 19:25
  • 2
    Also, don't use minimal for MWEs, use article, because minimal is not a proper class for actual use.
    – Alan Munn
    Oct 24, 2023 at 19:29
  • 2
    For NewExpandableDocumentCommand it's easy just use an e variant to expand before comparison, for NewDocumentCommand then not comparing is really the best answer. Oct 24, 2023 at 19:31

1 Answer 1

3

\NewExpandableDocumentCommand is for "document shortcuts" that expand to whatever the definition is, so here you can expand before comparing:

enter image description here

\documentclass{minimal}
\NewExpandableDocumentCommand\foo{}{n}
\begin{document}
\ExplSyntaxOn
\tl_if_eq:enTF {\foo} {n}
{ YES }
{ NO }
\ExplSyntaxOff
\end{document}

However \NewDocumentCommand makes a new command and the fact that its definition is n is more or less intentionally considered an implementation detail. You would have to drop to ltcmd/xparse internals to extract the inner definition (which is not impossible, one could look at \ShowCommand which does exactly that)

4
  • Your example did not work, but I was able to get it working using \cs_generate_variant:Nn \tl_if_eq:nnTF { enTF }; does that indicate that my L3 kernel is out of date?
    – karlh
    Oct 24, 2023 at 20:14
  • 1
    yes, we've been adding more e variants by default in recent releases. specifically my log shows L3 programming layer <2023-10-10> @karlh but adding the variant as you show is fine for older releases. Oct 24, 2023 at 20:22
  • 1
    I think this is ultimately the solution I desired, though tl_if_eq:xnTF has the side effect that if a user actually passed \foo as the argument in place of n, it fails; setting up tl_if_eq:xxTF seems to work as desired in this case. Thank you!
    – karlh
    Oct 24, 2023 at 20:42
  • 2
    @karlh sure you could use xx (or ee) if you want to expand both arguments Oct 24, 2023 at 20:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .