When to use TeX vs LaTeX for package writing

Technically using plain tex is not an option, plain is the format produced by inputting the file plain.tex into initex and that file is not used in LaTeX at all.

It is however true that many of the commands that are defined in plain TeX have commands of the same name defined in LaTeX, and in some of those cases, the definitions are the same.

The commands in the LaTeX format and the standard classes are written in a mixture of "low level" macros and TeX primitives that are more or less analogous to plain tex. At the time they were written (1985-1993) doing anything else would not have been an option, early versions of what is now called xparse were already available at that time but there was not enough memory left to process any real documents, and even test documents took "a while..."

Now it depends. It is of course always more efficient in machine time to use a lower level interface but may be less efficient in human time in development and maintenance. This applies to any computing language not just TeX. For most people most of the time it is better to write code in a high level system, but for some people for some core code it is still effective to write code in processor-specific machine code assembler as a human expert can still do better than a compiler.

If you use low level commands then it might be more efficient but you might break something. There was a question here recently when someone had gone \def\box{....} and then wondered why things didn't work. Similarly if your document is also using higher level packages such as expl3 or pgf then if you update the structures those packages need via the documented package interfaces then the structures are far more likely to be internally consistent than if you just poke in some new values with \let or \def.

On the other hand if, as often happens, your definition is a variation or extension on an existing definition then it makes sense to code it in the same style, for ease of code re-use but also for documentation reasons to make it more easy to see the differences. So it is not possible to give blanket advice that for latex2e all packages should be written in expl3 or whatever.

One other consideration that pushes towards low level code is that you may want the package to work with plain tex (and possibly context or eplain or lollipop or ...) without having to load a definitional layer such as expl3-generic or miniltx.tex. The ltluatex code for low level luatex support is for example written to work unchanged with plain TeX even though it is distributed as part of the LaTeX base.

So if starting a completely new code and you want to provide a natural interface and documentable structure to the code I would use expl3. If you are adapting or modifying existing code or have other real world constraints then it's complicated and the end result is usually a compromise.

The LaTeX kernel itself is very stable and (apart from some changes to address new engines such as luatex) has not really changed since LaTeX2e stabilised in the the 1990's. Since the 2015 release some bug fixes have been added but they are all guarded by conditional code in the source file which allows the latexrelease package to wind back the definitions to an earlier release if necessary.


So I got into the whole idea of learning plain TeX

OK, welcome:)

1. What is good practice for package writing?

Typically, plain TeX users don't use packages from third side. They started with fixed point which is plain.tex file and do own macros. But there is a problem about "reinventing wheel". For example they must do own macros for table of contents, colours, references, bibliography etc. So, I did a macro OPmac and released it as public available. The main principle is simplicity, see the summary. And second principle is:

Do not try to make new language level with plenty of keywords, identifiers and new syntax. Give simple default macros only and say: "if you need something different, redefine them." This is typical plain TeX approach. The most powerful language is ready to use: the TeX macro language.

If you use only TeX primitives and basic plain TeX macros (like \newcont allocator) in your packages then your code will be applicable everywhere: in plain TeX, LaTeX and ConTeXt, for example. Unfortunately, this "good practice" is not observed in LaTeX packages. For example the qrcode.sty is usable macro for QR codes printing results by \hrule, \vrule primitives. But this macro is mix of TeX primitives (like \def, \advance) basic plain TeX macros (like \newcount) and LaTeX macros (like \newcommand, \addtocounter, \newcounter). IMHO, this is very bad practice. The qrcode.sty is not applicable in plain TeX or ConTeXt, for example. So I removed the LaTeX specialities from qrcode.sty and released qrcode.tex here.

2. If I do use LaTeX in the package, what are the advantages and disadvantages...

Sorry, I don't see any advantages. The result is LaTeX specific, LaTeX dependent and this is not good idea. The TeX macro language is sufficiently powerful.

3. Also, how can I know for sure (without digging through the files that came with my distribution) if a plain old command is a TeX primitive

For example, what you see in the Index of TeXbook. Or in my book TeXbook naruby, the appendix B lists all TeX primitives and macros of plain.tex including explanation. The marks (used here) e, h, v, m mean that the control sequence is expandable, horizontal, vertical or math-mode primitive. And [plain] means plain TeX macro.

You cannot distinguish LaTeX macros from plain TeX macros by presence of @ character, because plain TeX includes control sequences with @ too. Unfortuately, this was not a good idea for name spaces. Namely, TeX is unable to deal with name spaces and the rules to put something to each new allocated control sequence is only agonised experiment to solve this. But plain TeX user knows the TeX primitives and he/she is able to allocate new names with respect to this "only one name space".


  1. Try to use as less package dependent macros as possible, and organize your general purpose ones in a small file. You may have a look at Paul Isambert's TeXapi and YaX packages, which may provide you with an interface to write format independent macros; they are used by his lecturer and navigator packages, which can run on Plain, LaTeX and ConTeXt.

  2. Skip.

  3. Grab a copy of TeX for the Impatient and keep it near your desk.