27

This morning I found myself writing a document where essentially the same text is repeated several times. Because I've been mucking around a lot recently learning LaTeX3, it took absolutely no thought and practically no time to write the following snippet.

\usepackage{xparse}
\ExplSyntaxOn
\newcommand{\tangentcount}[1]{
               \prg_case_int:nnn { #1 }
               {
                    { 2 } { exactly\ two }
                    { 1 } { exactly\ one }
               }
               { no }
}
\ExplSyntaxOff
\newcommand{\ietangents}[2]{%
    \tangentcount{#1} external and \tangentcount{#2} internal tangents.}

Granted, it would probably have been better to write:

\NewDocumentCommand{\tangentcount}{ m }
    {
               \prg_case_int:nnn { #1 }
               {
                    { 2 } { exactly\ two }
                    { 1 } { exactly\ one }
               }
               { no }
    }

It's also worth noting that I probably could have done something like

\usepackage{xparse}
\usepackage{xstring}
\NewDocumentCommand{\tangentcount}{ m }
    {%
        \IfEqCase{#1}{%
            {2}{exactly two}%
            {1}{exactly one}%
        }[no]%
    }

And certainly, I could have done something at the TeX level. But to build a switch function in TeX? The code just doesn't come naturally or quickly enough---I could probably write the whole document in the time it would take me to figure out how to get the switch done in TeX.

Now this is definitely a private document that I will really only ever use for today's class on account of a tangential question last week, please excuse the pun. It's probably a document that will just get left there on my harddrive, soon forgotten and never referred to again. So on a certain level, how I do this really does not matter.

But the question does come to mind, what are good practices?

I'm not writing a package: at least not yet. But who knows? Maybe I'll decide in a couple months that I really do want to put together all these little pieces of code for something I'll post publically or even publish. All this raises questions about the suitability of the code for the task at hand and how much potential refactoring of my code will I have to do.

For now it seems, there will be times when using LaTeX2e (or even some TeX) might be unavoidable. Things such as glue, drawing rules, setting up fonts, formatting text, inputting files, creating boxes (or maybe that's what coffins are about) appear to be out of the current scope of LaTeX3. To the extent that I understand the philosophy of the LaTeX3 authors, there may never be an explicitly LaTeX3 command such as \markup_text_bf:n.

In the above examples, I prefer the LaTeX3 solution over using xstring; not because I don't like xstring, but because it seems silly to slurp in an entire package when I'm already using macros and environments which have invoked expl3. But is this good practice?

So what are some general guidelines for deciding when one should resort to TeX, LaTeX2e, or LaTeX3?

2
  • 3
    The switch in TeX is \ifcase: Conditional cases expression. I.e.: \ifcase\numexpr#1-1\relax exactly one\or exactly two\else no\fi Commented Feb 4, 2013 at 20:06
  • 4
    Regarding \textbf: you seem to confuse “expl3” (the programming layer of LaTeX3) with “LaTeX3” (the format that will be the successor of LaTeX2e and most definitely will provide means for text formatting). Right now you have no choice but to use LaTeX2e (besides Plain TeX or conTeXt). What you can do is use “l3 in 2e” which is what expl3, xparse, xcoffins and friends are for (please correct me if I'm wrong).
    – cgnieder
    Commented Feb 4, 2013 at 20:13

1 Answer 1

27

I believe it is good practice. There are hundreds of functions in the current LaTeX3 kernel that make a macro programmer's life easier.

I wouldn't use such a dramatic indentation as you do and surely I'd use \NewDocumentCommand:

\NewDocumentCommand{\tangentcount}{ m }
 {
  \int_case:nnn { #1 }
   {
    { 1 } { exactly ~ one }
    { 2 } { exactly ~ two }
   }
   { no }
 }

or, even better,

\NewDocumentCommand{\tangentcount}{ m }
 {
  \ellett_tangentcount:n { #1 }
 }
\cs_new:Npn \ellett_tangentcount:n #1
 {
  \int_case:nnn { #1 }
   {
    { 1 } { exactly ~ one }
    { 2 } { exactly ~ two }
   }
   { no }
 }

separating the user command from the inner function. This may be easily extended to any number of intersection points

\cs_new:Npn \ellett_tangentcount:n #1
 {
  \int_compare:nTF { #1 = 0 }
   { no }
   { exactly ~ \int_to_arabic:n { #1 } }
 }

Notice the use of ~ to denote a space in the output, to be preferred to "control space". One may add a check that the number is greater than zero.

Notice also that \prg_case_int:nnn is an obsolete name for the current \int_case:nnn function.

Why \cs_new:Npn? Because the \int_compare:nTF and \int_case:nnn functions are marked with a filled star in the documentation, so they are "fully expandable" and thus also \ellett_tangentcount:n can be used in a "pure expansion" context.

2
  • 3
    You've recommended that I use ~ before, and I've tried to follow your suggestion. In this particular example, I opted out because, as I understand it, ~ will prevent a line break at that point. Is this no longer true within the guts of expl3?
    – A.Ellett
    Commented Feb 4, 2013 at 20:43
  • 13
    @A.Ellett In the LaTeX3 programming environment ~ denotes a plain space token (in output), as normal space tokens are ignored; it's not, like in the "document" environment, a non breaking space.
    – egreg
    Commented Feb 4, 2013 at 20:52

You must log in to answer this question.

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