TransWikia.com

if statements in latex

TeX - LaTeX Asked by Nachiket on March 6, 2021

I’m trying to understand why the mymap function in the following code does not produce any output when called with a variable in a for loop (see myloop). It produces output when text is explicitly passed to it. See myloopb. Sorry for the simple question, I wasn’t able to understand explanations of the if and ifx statements on stackexchange and other places. If it matters I’m using pdflatex from MikTex on Windows.

documentclass[12pt]{article}
usepackage{pgffor}

% define variables
defvala{aa}
defvalb{bb}

% this produces different output depending on #1
newcommand{mymap}[1]{
  deftemparg{#1}
  ifxtempargvala
  Condition 1 is true
  fi
  ifxtempargvalb
  Condition 2 is true
  fi
}

newcommand{myloop}{
  foreach myvar in {vala,valb}{
    % this does not produce any output
    mymap{myvar}
  }
}

newcommand{myloopb}{
    % this produces output
    mymap{aa}
    mymap{bb}
}

begin{document}
section{Using myloop does not produce output}
% no output
myloop
section{Using myloopb produces output}
% produces output
myloopb
end{document}

2 Answers

The issue is expansion here. ifx tests whether the two following macros (if macros are passed) have the same meaning. In the first case temparg has the meaning macro:->myvar, whereas vala has the meaning macro:->aa and valb is macro:->bb.

Your myvar has macro:->vala and macro:->valb as meaning in your loop. If you expand it twice before mymap takes its argument, you get the correct meaning of temparg. You can trigger earlier expansion with expandafter<tokA><tokB>, which will expand <tokB> before <tokA> is expanded. So inside your loop use expandafterexpandafterexpandaftermymapexpandafterexpandafterexpandafter{myvar}.

If your input is always fine to be fully expanded (it is in your example), you could use edeftemparg{#1} instead, which is much cleaner than the expandafter-chain proposed above.

documentclass[12pt]{article}
usepackage{pgffor}

% define variables
defvala{aa}
defvalb{bb}

% this produces different output depending on #1
newcommand{mymap}[1]{%
  edeftemparg{#1}%
  ifxtempargvala
  Condition 1 is true%
  fi
  ifxtempargvalb
  Condition 2 is true%
  fi
}

newcommand{myloop}{%
  foreach myvar in {vala,valb}{%
    % this does not produce any output
    mymap{myvar}%
  }%
}

newcommand{myloopb}{%
    % this produces output
    mymap{aa}%
    mymap{bb}%
}

begin{document}
section{Using myloop does not produce output}
% no output
myloop
section{Using myloopb produces output}
% produces output
myloopb
end{document}

Correct answer by Skillmon on March 6, 2021

You can define a general purpose string case comparison.

documentclass[12pt]{article}
usepackage{pgffor}

% a string comparison function
ExplSyntaxOn

NewExpandableDocumentCommand{StringCaseTF}{mm+m+m}
 {% #1 = string input, #2 = cases,
  % #3 = code to execute after a match
  % #4 = code to execute after no match
  str_case_e:nnTF { #1 } { #2 } { #3 } { #4 }
 }

ExplSyntaxOff

% define variables (not with def)
newcommandvala{aa}
newcommandvalb{bb}

% this produces different output depending on #1
newcommand{mymap}[1]{%
  StringCaseTF{#1}{
    {vala}{Condition 1 is true}
    {valb}{Condition 2 is true}
  }{par There was a match!}{par There was no match!}%
  par
}

newcommand{myloop}{%
  foreach myvar in {vala,valb,x}{
    % this does not produce any output
    mymap{myvar}
  }
}

begin{document}

myloop

end{document}

Load xparse if you don't have the most recent LaTeX kernel.

enter image description here

The third or fourth arguments to StringCaseTF can be left empty, of course.

Answered by egreg on March 6, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP