[Tex/LaTex] When using \IfEq to compare strings, is it one of those times when I should use an expandable xparse command

conditionalsxparsexstring

I recently asked
How can I migrate commands and environments from LaTeX2e to LaTeX3? [XeTeX]

While that question is good, the answer is likely quite complex and would take a some time to effectively answer (at the time of writing, there are no answers, however, there are a couple of helpful comments).

This question addresses one of the speed bumps I ran into on the road to LaTeX3.

Using xparse LaTeX3 syntax, I am defining:

  1. a command holding a value (functions as variable)
  2. a user command to reset that value
  3. a conditional statement using xparse's \IfEq

Syntax for \IfEq:

\IfEq{〈stringA〉}{〈stringB〉}{〈true〉}{〈false〉}

From the xparse manual:

There are very rare occasion when it may be useful to create functions using a fully expandable argument grabber. To support this, xparse can create expandable functions as well as the usual robust ones. This imposes a number of restrictions on the nature of the arguments accepted by a function, and the code it implements. This facility should only be used when absolutely necessary; if you do not understand when this might be, do not use these functions!

Note there is a typo in version "Released 2014/11/25": *occasions*

Updated Code

From my understanding, \jkoclass needs to be expanded, but will not be expanded with \NewDocumentCommand. Should I be using \DeclareExpandableDocumentCommand?

I realized that my example code was not written the way it should have been when I initially opened the question. Here is the code that I indented:

\documentclass{article}
\usepackage{xparse}
\usepackage{xstring}
\DeclareExpandableDocumentCommand{\jkoclass}{}{I}
\NewDocumentCommand{\jkosetclass}{ m }{\RenewDocumentCommand{\jkoclass}{}{#1}}

\NewDocumentCommand{\jkoimagepath}{}{
    \IfEq{\jkoclass}{I}
        {Value is I}
        {Value is NOT I}
    }
\begin{document}
\jkoimagepath{} (should result in: Value is I)

\jkosetclass{II}
\jkoimagepath{} (should result in: Value is NOT I)
\end{document}

enter image description here

Original Question Code

\documentclass{article}
\usepackage{xparse}
\usepackage{xstring}
\NewDocumentCommand{\jkoclass}{ m }{I}
\NewDocumentCommand{\setjkoclass}{ m }{\RenewDocumentCommand{\jkoclass}{m}{#1}} 
\IfEq{\jkoclass}{I} %<-- \jkoclass is protected automatically by the xparse definition and will therefore not be expand as desired.
  {Class is I}
  {Class is II}
\begin{document}
\setjkoclass{II}
\jkoclass{}
\end{document}

Best Answer

You're taking the wrong approach; you can certainly have a user level command \jkoclass that prints something, but if what it prints is variable data, this data should be allocated its own variable.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

% allocate a (global) variable
\tl_new:N \g_macmadness_jko_class_tl

% initialize the value
\tl_gset:Nn \g_macmadness_jko_class_tl { I }

% define a user level command for printing the value
\NewDocumentCommand{\jkoclass}{}
 {
  \tl_use:N \g_macmadness_jko_class_tl
 }

% define a user level command for changing the value
\NewDocumentCommand{\setjkoclass}{m}
 {
  \tl_gset:Nn \g_macmadness_jko_class_tl { #1 }
 }

\ExplSyntaxOff

Suppose now you want to define a new user level command for printing something that depends on the variable to contain I or not.

Add, in the programming environment,

\NewDocumentCommand{\jkoclassifI}{}
 {
  \tl_if_eq:VnTF \g_macmadness_jko_class_tl { I }
   { Class~is~I }     % true branch
   { Class~is~not~I } % false branch
 }
\cs_generate_variant:Nn \tl_if_eq:nnTF { V }

The last instruction is for making available in the programming environment a variant of the token list equality check function that takes as its first argument a token list variable.

Spaces in output in the programming environment must be specified by ~, because ordinary spaces are ignored.

Related Question