7

I am using a \protected\def as that solved an earlier issue of mine. I need to compare this value of the token to see if it is initialized to the same value as the \protected\def in different ways.

The MWE below checks the cases I need. I really would prefer to not make any changes to how the variables are declared, but rather define a custom version of \MyIfStrEq to perform the comparison as required.

Notes:

  • The MWE below yields the correct results if I simply remove \protected, but I need to use the \protected in another case as per the referenced question below.
  • I normally would not use magical text such as "special" beyond the premable, but in this case the text I need to compare to is coming from the file system.

References:

Code:

\documentclass{article}
\usepackage{xstring}
\usepackage{xparse}


\NewDocumentCommand{\MyIfStrEq}{m m m m}
  {%
   \IfStrEq{#1}{#2}{#3}{#4}%
  }
%\NewDocumentCommand{\MyIfStrEq}{m m m m}
%  {%
%   \ifx#1#2%
%       #3%
%   \else%
%       #4%
%   \fi%
%  }


%% -------------------------------------------------------------
%% Would prefer to NOT change code from here to \begin{document}
  \protected\def\SpecialValue{special}
  \newtoks{\MyToken}
  \MyToken={\SpecialValue}
%% -------------------------------------------------------------



\begin{document}
\MyIfStrEq{\SpecialValue}{special}{Pass 1}{Fail 1}%

\MyIfStrEq{\the\MyToken}{special}{Pass 2}{Fail 2}%

\MyIfStrEq{\the\MyToken}{\SpecialValue}{Pass 3}{Fail 3}%
\end{document}
  • Doing \MyToken={\SpecialValue} stores '\SpecialValue' in \MyToken. The most 'obvious' solution to me is to do \MyToken=\expandafter{\SpecialValue}, i.e. to expand the marker exactly once before assignment. However, I'm not clear that this is allowed. Are we permitted to make assumptions abut the input, for example that the second argument to \MyIfStrEq may be either a literal or a macro which may be expanded exactly once? – Joseph Wright May 15 '13 at 6:04
  • @JosephWright: I'd prefer to not change \MyToken but anything that is localized to \MyStrEq would be fine. The second parameter will be a value of a \def from a modified version of GetShellOutput from Specify file name shell access via \@@input. If it makes a difference I can add that to the MWE. – Peter Grill May 15 '13 at 6:34
5

If I have understood the requirements correctly, something like

\documentclass{article}
\usepackage{xstring}
\usepackage{xparse}

\NewDocumentCommand{\MyIfStrEq}{m m m m}
  {%
    \begingroup
    \edef\x{%
      \endgroup
      \noexpand\MyIfStrEqAux{#1}{#2}%
    }%
    \x{#3}{#4}%
}
\protected\def\MyIfStrEqAux#1#2#3#4{%
  \IfStrEq{#1}{#2}
    {#3}
    {\expandafter\IfStrEq\expandafter{#1}{#2}{#3}{#4}}%
}

%% -------------------------------------------------------------
%% Would prefer to NOT change code from here to \begin{document}
  \protected\def\SpecialValue{special}
  \newtoks{\MyToken}
  \MyToken={\SpecialValue}
%% -------------------------------------------------------------


\begin{document}
\MyIfStrEq{\SpecialValue}{special}{Pass 1}{Fail 1}%

\MyIfStrEq{\the\MyToken}{special}{Pass 2}{Fail 2}%

\MyIfStrEq{\the\MyToken}{\SpecialValue}{Pass 3}{Fail 3}%
\end{document}

will work. The approach here is as follows. We start with the assumption that #1 and #2 may consist of:

  • A protected macro (such as \SpecialValue)
  • The use of a toks (such as \the\MyToken)
  • Text (such as special)

The \edef will not affect the protected macro or text cases, and will expand the toks case exactly once. There are then two comparisons:

  1. Do the two arguments now match?
  2. If not, do they match if we expand the first one exactly once.

Looking at the three demo cases, we get the logic:

  1. The \edef changes nothing, so the first test is false (comparing \SpecialValue with special). The single expansion expands \SpecialValue to special, and so the second test is true.

  2. The \edef converts \the\MyToken to \SpecialValue, and we proceed as in case (1).

  3. The \edef converts \the\MyToken to \SpecialValue, meaning that the first test compares \SpecialValue and \SpecialValue, which are the same and so the first test is true and we never expand \SpecialValue.

If the second argument may need to be expanded (if we can have literal text in the first and a macro in the second) then some argument shuffling will be needed.

The above works, but I would caution against it. In general it's much better 'style' to specify the nature of arguments: the 'perhaps expand' business is risky as it might blow up if the argument is something you didn't allow for.

  • Yep that seems to work in the MWE. Will check it in my code tomorrow. Thanks... – Peter Grill May 15 '13 at 7:48
  • This seems to be dependent on the order of #1 and#2 of \MyIfStrEq. Is this expected? It would be better to not have to think of the order of the parameters when invoking \MyIfStrEq. For instance \MyIfStrEq{special}{\SpecialValue}{Pass 1}{Fail 1} fails the test. – Peter Grill May 15 '13 at 18:43
  • @PeterGrill I did say I was not sure I understood the requirements. You can certainly extend what I've done using a second (and perhaps third) auxiliary (one to expand the second argument but not the first, and one to expand both). I'm very wary of this, though, since I'd be much keener on having a 'tight' specification on the nature of the input to your test. Arguments which might or might-not expand are in my experience not very helpful long-term. – Joseph Wright May 15 '13 at 21:10
  • Yeah, I should be able to extend it, and would if I actually understood the expansion related issues. But since I don't understand expansion, not sure I can do it. The reason I don't know the argument types is that I am processing a list which is partially specified in the .tex file using \SpecialValue and partially determined form the filesystem where it comes in as text special. – Peter Grill May 15 '13 at 21:25

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.