2

In LaTeX3, I could define a function for comparing a token list to a string

\cs_generate_variant:Nn \tl_if_eq:nnTF { V }
\cs_new_nopar:Npn \module_compare:n #1
  {
    \tl_if_eq:VnTF \g_some_tl { #1 } { 1 } { 0 }
  }

But now I want to make this function exhaustively expandable. Are there any other similar functions other than \tl_if_eq:nnTF that I could use?


Edit: to give more context to my problem, I added the following unworking example. (Note that I need to use \ifnum for some reasons.)

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\tl_set:Nn \g_some_tl {abc}
\cs_generate_variant:Nn \tl_if_eq:nnTF { V }
\cs_new_nopar:Npn \mycompare #1
  {
    \tl_if_eq:VnTF \g_some_tl { #1 } { 1 } { 0 }
  }
\ExplSyntaxOff
\begin{document}
\def\mytest#1{\ifnum \mycompare{#1} > 0 do some\else do other\fi}
\mytest{uvw}
\mytest{abc}
\end{document}

According to Joseph Wright's comments, replacing \tl_if_eq:VnTF with \str_if_eq:VnTF solves my problem.

  • 1
    Your title say 'string' but your code is a token list comparison: which one do you want? A string-based test is easy using \str_if_eq_x:nn(TF). – Joseph Wright Feb 11 '15 at 9:55
  • \ifx is an expanable primitive for comparing a token lists in TeX. – wipet Feb 11 '15 at 10:02
  • @JosephWright Sorry, now I have edited my title. – Z.H. Feb 11 '15 at 10:03
  • Could we have a bit more context here? I can think of at least one approach to the problem but it is rather tricky so before I put that down wonder if this is an 'X-Y' problem. – Joseph Wright Feb 11 '15 at 10:47
  • @JosephWright I have added a complete example. – Z.H. Feb 11 '15 at 11:44
2

Token list comparison cannot be expandable, because the only way TeX has for comparing them is to make them the replacement text of macros.

However, all the engines (except for Knuth TeX) implement an expandable “string comparison” that basically works with \detokenize (details are a bit more involved).

With \usepackage{pdftexcmds} you have available \pdf@strcmp (it is called \pdfstrcmp by pdftex, \strcmp by XeTeX and it's emulated with a Lua script in LuaTeX). The code

\pdf@strcmp{<string-A>}{<string-B>}

returns zero if the strings are equal (after expansion, here the details become involved), 1 or –1 otherwise.

This is also available with expl3 as \str_if_eq:nn(TF) (the parentheses mean that one or both the specifiers can be omitted) or \str_if_eq_x:nn(TF). The former doesn't perform expansion on its first two arguments, the latter does.

In your case you could do

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mytest}{m}
 {
  \zh_mytest:n { #1 }
 }

\cs_new:Npn \zh_mytest:n #1
 {
  \str_if_eq:VnTF \g_zh_fixed_tl { #1 } { 1 } { 0 }
 }
\cs_generate_variant:Nn \str_if_eq:nnTF { V }

\tl_gclear_new:N \g_zh_fixed_tl
\tl_gset:Nn \g_zh_fixed_tl { abc }
\ExplSyntaxOff

\begin{document}
\edef\test{\ifnum\mytest{x}>0 Equal\else Unequal\fi}

\texttt{\meaning\test}

\edef\test{\ifnum\mytest{abc}>0 Equal\else Unequal\fi}

\texttt{\meaning\test}
\end{document}

enter image description here

The usage of \edef is just to show that the macro is fully expandable. However, mixing in this way expl3 code and old style code is not really recommended.

I'd prefer something like

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mytestTF}{mmm}
 {
  \zh_mytest:nnn { #1 } { #2 } { #3 }
 }

\cs_new:Npn \zh_mytest:nnn #1 #2 #3
 {
  \str_if_eq:VnTF \g_zh_fixed_tl { #1 } { #2 } { #3 }
 }
\cs_generate_variant:Nn \str_if_eq:nnTF { V }

\tl_gclear_new:N \g_zh_fixed_tl
\tl_gset:Nn \g_zh_fixed_tl { abc }
\ExplSyntaxOff

\begin{document}
\edef\test{\mytestTF{x}{Equal}{Unequal}}

\texttt{\meaning\test}

\edef\test{\mytestTF{abc}{Equal}{Unequal}}

\texttt{\meaning\test}
\end{document}
  • I was thinking for a token-based version one might go for \str_if_eq:nn(TF) first then using a modified version of the old 'almost OK' string comparison based on inserting multiple \if tests and using \ifx instead. I guess the OP didn't need a token test after all! – Joseph Wright Feb 11 '15 at 13:23
  • @JosephWright I could not understand what's the differences between token-based and string-based comparisons? Sorry for misleading you. – Z.H. Feb 11 '15 at 13:52
  • @Z.H. That probably constitutes a new question (if we don't already have one on this). Basically, TeX deals with tokens so for example typically text is made up of four 'letters' but with some \catcode changes they might not be. Matching the characters and matching the tokens are not the same thing. – Joseph Wright Feb 11 '15 at 13:54

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.