32

I'm thoroughly enjoying using LaTeX3 for programming my LaTeX stuff and the more I use it, the easier it gets and the more I shudder at returning to LaTeX2e or even pure TeX! But every now and again I find myself needing to interact with LaTeX2e at the programming level. As an example, there may be a conditional set by some LaTeX2e package that I want to test in my package written in LaTeX3. I could do this using the LaTeX2e method:

\ifcondition
  <stuff>
\else
  <other stuff>
\fi

but I don't like that, partly because then I have to remember to worry about \expandafters if I want to ensure that the \else and \fi don't interfere with the inner code. So I'd rather stick with the LaTeX3 syntax.

My current code for the above is:

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
{
  \if_meaning:w #1 \iftrue
  \prg_return_true: \else: \prg_return_false: \fi:
}

Is this a reasonable approach, or is there a better way?

Similarly, (I hope I can get away with two questions here since they are so closely related) how should I interact with LaTeX2e macros? Let's say a package defines a macro \def\something{This is some text we'll save for later.} and I want to mess with that using LaTeX3. Am I right in thinking that I should regard is as a token list (tl)? Are there any pitfalls to doing so?

1

2 Answers 2

17

Your code will return false when \latex_if:NTF \ifmmode is used, because \ifmmode is not the same as \iftrue, even if we are in math mode. It works only with defined conditionals such as \if@minipage, because this is introduced by \newif, so it is either \iftrue or \iffalse.

Your function should work the same both for defined conditionals and primitive ones to have maximum flexibility; you might want to do

\bool_if:nTF { \latex_if_p:n {@minipage} || \latex_if_p:n {mmode} }
 {true code}
 {false code}

(which is quite improbable, but shows the idea).

I'd do it differently:

\prg_new_conditional:Npnn \latex_if:n #1 {p,T,F,TF}
 {
  \use:c{if#1} \prg_return_true: \else: \prg_return_false: \fi:
 }

to be used as

\latex_if:nTF {mmode} {code for math mode} {code for non math mode}

If you prefer, you can do

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
 {
  #1 \prg_return_true: \else: \prg_return_false: \fi:
 }

but this has the disadvantage of requiring \makeatletter when \if@minipage is tested.

2
  • Interesting approach. Can this test be used inside \bool_if:nTF? Jun 18, 2013 at 19:36
  • @MarcoDaniel yes it can the _p variant Jun 18, 2013 at 19:40
15

To answer your first question, I would say the answer is yes, this is the right approach and it is clean. But the definition could be made simpler if we assume that the argument is always a 2e conditional:

\prg_new_conditional:Npnn \latex_if:N #1 {p,T,F,TF}
{
   #1 \prg_return_true: \else: \prg_return_false: \fi:
}

Thanks for @egreg to point this out.

It would also allow you to use those 2e booleans in predicates, e.g.,

\bool_if:nTF
   {
     \latex_if_p:N \if@minipage ||
     \latex_if_p:N \ifinner     ||
     ...

But for \latex_if_p:N \ifinner one could of course use the expl3 equiv directly, i.e., \mode_if_inner_p:.

I'm not so keen on the suggestion of something like this (as suggested in the comment):

 \bool_if:nTF
    {
      \if@minipage 1 \else 0 \fi || %compatible to LaTeX2e
      \ifinner 1 \else 0 \fi || %compatible to LaTeX2e

why? Very simple, it exposes internal implementation details of the expl3 boolean implementation and that is a not good. If at all it should return \prg_return_true: but even that ... :-)

As to the second question, the answer would be: it depends. Clearly any 2e macro that is essentially a "token list" should be manipuated as such and so, yes it would be a "tl" and no there should be no pitfalls there.

You could, of course, provide an explicit interface translating into l3 names and back into 2e names once your done, but in my opinion you only gain an additional level of making errors (and extra processing time) in that case.

More complicated is anything that is a macro with arguments.

If you just want to use it, then I think it would be worth considering to define an expl3 conforming name at the very beginning and use that throughout. Makes the code much cleaner in that case.

If, for some reason, you need to manipulate it, then all the \cs_... functions should work and for the rest one would need to see on a case by case basis.

So far my thoughts, maybe others have additional ones.

5
  • The test \latex_if_p:N \ifinner will always return false. It's only good for defined conditionals like \if@minipage
    – egreg
    Jun 18, 2013 at 19:17
  • @egreg of course, thanks, I could blame it on the heat, but I simply wasn't thinking straight, so the condition should be made simpler without comparison. Will update. Jun 18, 2013 at 19:32
  • It's true that one can use \mode_if_inner_p: or \mode_if_inner:TF for testing \ifinner, but I find it useful, especially in a LaTeX2-compatibility environment, to be able to pass the conditional name as an argument to a "catch-all" function.
    – egreg
    Jun 18, 2013 at 19:44
  • @egreg yes the use of :n and then constructing the conditional is even better, especially as this then also avoids a 2e \if constract without matchin \fi be seen by the scanner. Jun 18, 2013 at 20:11
  • I see no mention that defining a command such as \latex_... in a package is not good practice. Unless Andrew registers that prefix... which would probably not be wise. Jul 7, 2013 at 3:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .