1

The following code does not work. I think maybe it is because of \f.

So my question is: how to get the value from a macro immediately(in my case I want \f get abc immediately)? And is it possible to define the macro \f by \edef?

I tried \edef\f{\ifthenelse{\equal{a}{a}}{abc}{def}} and failed.

\documentclass{article}
\usepackage{ifthen,xstring}
\begin{document}
\newcommand\f{\ifthenelse{\equal{a}{a}}{abc}{def}}
\def\g{abc}
\IfStrEq{\f}{\g}{Yes}{No}
\end{document} 
3

The issue is expandability, \ifthenelse isn't expandable. To compare two strings with expanding them before comparison you can use \str_if_eq:eeTF from expl3. Note that string comparison doesn't consider category codes, so the following isn't entirely equal to your \ifthenelse implementation (that would consider category codes).

\documentclass[]{article}

\ExplSyntaxOn
\cs_new_eq:NN \myifstreq \str_if_eq:eeTF
\ExplSyntaxOff


\begin{document}
\newcommand*\f{\myifstreq{a}{a}{abc}{def}}
\newcommand*\g{abc}
\myifstreq{\f}{\g}{Yes}{No}

\end{document}
3
  • How can I know if a macro is expandability? – lyl Jun 5 at 12:36
  • @lyl in the case of macros defined in expl3, you can take a look at texdoc interface3, every expandable macro is marked with a red star next to its name in that reference. Else a simple rule of thumb is: If it needs any assignments it can't be expandable. If it is defined as a "robust" or "protected" macro, it isn't expandable. If it uses optional arguments it most likely isn't expandable (there are a few mechanisms to expandably get optional arguments, but those are used relatively rare). Best you search for a good explanation (and if you don't find any, ask a question). – Skillmon Jun 5 at 12:39
  • Thank you so much! – lyl Jun 5 at 12:43
2

Your problem is that you are using non-expandable LaTeX macros instead directly TeX primitives. The \if... primitives are expandable:

\def\f{\ifx aaabc\else def\fi}  % instead \newcommand\f{\ifthenelse{\equal{a}{a}}{abc}{de
\def\g{abc}
\edef\test{\f} % the current (expandable) value of \f in in \test
\ifx\g\test Yes\else No\fi % instead \IfStrEq{\f}{\g}{Yes}{No}
\bye

The \if... commands are described in TeX in the Nutshell, for example.

2
  • Many thanks for your solution. In my example, charactor a is used for comparation. How to compare strings by Tex primitives? It seems that \ifx aaaa is no not a correct way. – lyl Jun 5 at 22:13
  • 2
    TeX does not use strings but only tokens or tokens lists. You cannot compare what does not exists in TeX. But extensions of TeX (pdfTeX or XeTeX) have \pdfstrcmp primitive which converts two token lists to strings, does comparison and returns -1, 0 +1. This result can be compared by \ifnum. All these primitives are expandable. LuaTeX can compare strings at Lua level, \directlua is expandable. – wipet Jun 6 at 3:21
1

The problem is that you're using \IfStrEq which is meant to compare strings, and for \ifthenelse to do its magic, it doesn't really evaluate to a string. As you noticed, \edef doesn't help in this context.

What you need to do, is to modify your command to define a macro with the desired result, e.g.,

\newcommand\f{\ifthenelse{\equal{a}{a}}{\def\foo{abc}}{\def\foo{def}}}

(if you're not concerned about \f being reusable, you could use \def\f instead of \def\foo at that point. Then your call to \IfStrEq evaluates as expected.

1
  • Would you please say more about why my version of \newcommmand\f" can not give the value of abc` to \f ? And why is it impossible to design the macro \f by edef? – lyl Jun 5 at 4:40

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.