Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

First of all: the package xstring cannot recognize a \par as argument. When I for example do this:

\usepackage{xstring}

\def\apar{\par}
\def\str{a string}

\IfStrEq{\str}{\par}{% true part
}{% false part
}

It results in an error. Why that the package specially made for strings has not got a check on that, I have no clue..


Another way of checking if a string is equal to \par can be achieved by using \ifx, but this has limits too. Look at the following example:

\def\apar{\par}
\def\str{\par}

First case:\\
\ifx\str\apar  % compare \str with a variable
  Str is a par.
\else
  Str is not a par.
\fi
\par
Second case:\\
\ifx\str\par  % compare \str with \par
  Str is a par.
\else
  Str is not a par.
\fi

This gives the output:

First case:
Str is a par

Second case:
Str is not a par

Not that I have problems with it, but I'm just asking myself why this is..

share|improve this question
1  
\IfStrEq (more precisely the internal macro \@xs@IfStrEq@@) does not accept \par as an argument because it's not \long. Notice that \apar and \par are different as far as \ifx is concerned: the former "expands to \par", the latter is \par. –  egreg Jul 20 '12 at 14:30
    
Thanks again :) –  Didii Jul 20 '12 at 14:42
add comment

1 Answer 1

up vote 7 down vote accepted

A macro can be defined with the prefix \long (this is done by default in \newcommand) and so \par is allowed in its arguments (if any). Otherwise \par is not accepted and throws an error.

In particular \IfStrEq is built around \@xs@IfStrEq@@ which the package author decided not to make \long.

I would be very cautious in using \IfStrEq with something read in from a file (which I suppose is what you want to do to test if a read in line is empty): if the line contains arbitrary commands, the full expansion performed by \IfStrEq could lead to a disaster; for instance, if \textbf appears in the line, the full expansion will die miserably.

When you do

\read\file to \fline

and the line contains foo\bar baz, this is equivalent to

\def\fline{foo\bar baz }

(notice the trailing space). If the line is empty, this becomes

\def\fline{\par}

(because this is how TeX interprets an empty line). That's why the "emptyness" can be tested by

\def\apar{\par}
\ifx\fline\apar

because \ifx tests whether the first level expansion of the macros is the same (there are more rules for when the tokens are not macros, but in this case they are).

If you prefer a syntax similar to \IfStrEq, then you can define

\makeatletter
\newcommand\IfEmptyLine[1]{%
  \ifx#1\apar
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

and use it as

\IfEmptyLine{\fline}{<code for the empty case>}{<code for the nonempty case}

Why does \ifx\apar\par return false? The answer is in one of the rules I didn't mention before. The first token is a macro (defined with \def), while \par is a TeX primitive (actually it could be redefined, and LaTeX does it from time to time, but it's pretty safe to assume that in normal parts of the document \par has the primitive meaning). A macro and a primitive are never considered equal by \ifx, because the former has a first level expansion and the latter doesn't.

If \par had been redefined, the test would return false again, unless a devious programmer had said \def\par{\par}. While this could be useful in very special circumstances, you can safely assume that when you're reading a file it's not in force, as a free standing \par token would lead to a vicious circle that can be stopped only by pulling the plug.

share|improve this answer
    
Ok, thanks for the extensive answer :) –  Didii Jul 23 '12 at 8:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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