3

I apologize if this is too newbie or a duplicate, but I've banged my head against it long enough, and searched without success. :(

I am trying to use an \if to test for an empty string without success and have traced it to my understanding of the \if itself. I have added sample code showing how I'm misusing \if in a real simple way:

\def\tmpOne{hello}
\tmpOne %shows that \tmpOne produces hello
\if{\tmpOne}{hello}
goodbye %This is never reached.
\fi

Closer to my actual application is:

\newcount\tmpInd

\def\funcOne{%
\advance\tmpInd by 1 
\if{\testEmpty{\readHistory{\value\tmpInd}}}{<NOT EMPTY>}
\funcOne
\fi
}   
%where \testEmpty returns either <EMPTY> or <NOT EMPTY>
%and \readHistory is my own previously defined function
%(They work as expected outside of this context)

Any help for my obviously weak understanding would be appreciated. :)

Edit: Due to information in one of the comments, I have added some extra details of my particular use case...

The definition for \testEmpty is:

\newcommand{\testEmpty}[1]{\setbox0=\hbox{#1}\ifdim\wd0=0pt<EMPTY>\else<NOT EMPTY>\fi}

The definition for \readHistory is:

\newcommand{\readHistory}[1]{\getdata[#1]\myChangeHistory}

The definition for \getData is:

\def\getdata[#1]#2{\csname data:\string#2:#1\endcsname}

The data is stored with \storeData:

\def\storedata#1#2{\tmpnum=0 \edef\tmp{\string#1}\storedataA#2\end\expandafter\def\csname data:\tmp:0\endcsname{\tmpcnt}}
\def\storedataA#1{\advance\tmpnum by1
\ifx\end#1\else
  \expandafter\def\csname data:\tmp:\the\tmpnum\endcsname{#1}%
  \expandafter\storedataA\fi
}

Note: I have patched these together by trawling the internet, and only partly understand them (but they all do what I want).

5

Your code is doomed to failure. The conditional \if tests character code equality of the next two unexpandable tokens it finds after it, performing expansion until unexpandable tokens remain. So

\if{\tmpOne}{hello} goodbye \fi

sees {, which is unexpandable and then expands \tmpOne; after this expansion the input stream is

\if{hello}{hello} goodbye \fi

and, since { and h aren't the same unexpandable token as far as \if is concerned (their character codes differ), the conditional returns false and TeX ignores everything up to the first matching \else or \fi. No \else is found, so what remains is

\fi

which has empty expansion; next TeX goes on.

Without knowing more about \readHistory it's impossible to suggest alternative strategies.

  • Thanks for responding... If I understand the terminology correctly, \testEmpty expands to either "<EMPTY>" or "<NOT EMPTY>", depending on the expansion of \readHistory{3}. Therefore \if will always end up comparing < and E or < and N. Is that correct? (Assuming I get rid of the braces {}) – Sean Cooper May 18 '16 at 17:18
  • @SeanCooper It much depends on those macros are defined. A token list not producing output is not necessarily empty. – egreg May 18 '16 at 17:41
  • Thanks... I have updated the main question to include several layers of definition. ... Correct me if I'm misunderstanding, but it seems I need to adjust things to indicate "empty" vs. "not empty" with a single character and get the functions to expand before comparison? – Sean Cooper May 18 '16 at 17:53
  • @SeanCooper no. Your \testempty does not work by expansion (and does not test if its argument is empty) the first non expandable token in its expansion is \setbox so the \if in your code always tests { against \setbox and is therefore always false and skips to the \fi – David Carlisle May 18 '16 at 22:37
  • @DavidCarlisle ... I hear what you are saying... but it doesn't behave that way in practice. In actual practice it works as intended. It does NOT always evaluate false. :) Edit: It occurred to me that you might be refering to the if statement refering to \testempty rather than the \testempty itself. If that is the case, I withdraw the comment. :P I will look into that. – Sean Cooper May 19 '16 at 13:29
1

I marked egreg's answer as accepted, because it actually answered the question as written.

I ended up solving the problem a slightly different way and am posting this answer in case it benefits anyone else.

I ended up using a \newif.

\newif\iftestEmptyBool
\newcommand{\testEmpty}[1]{\setbox0=\hbox{#1}\ifdim\wd0=0pt \testEmptyBooltrue\else \testEmptyBoolfalse\fi}

\newcounter{tmpind}
\setcounter{tmpind}{0}
\def\funcOne{\addtocounter{tmpind}{1}\testEmpty{\readHistory{\thetmpind}}\iftestEmptyBool\else\funcOne\fi}

The \testEmpty is now run beforehand and \iftestEmptyBool is used as the conditional.

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.