100 Languages Speedrun: Episode 28: TeX
Tags: tex, latex
Published: 2021-12-18 23:15:56

TeX (pronounced like "tech") is a typesetting system, which is still used for writing research papers in Mathematics, Computer Science, Physics, and related disciplines, and pretty much nothing else. Everyone else moved on to either WYSIWYG editors like Word, or to HTML, or maybe Markdown or something like that. But it still survives in its niche.

Like every typesetting system, it comes with its own embedded programming language, and that's what we're going to use.

Technically TeX is just the original system, and we'll also be using a lot of *TeX things (MacTeX, LaTeX, pdftex etc.), but that's meaningless distinction, so I won't mention it anymore.

### Hello, World!

```latex
\documentclass{minimal}

\newcommand\hello[1]{Hello, #1!}

\begin{document}
\hello{World}
\end{document}
```

Which with `pdflatex hello.tex` generates a PDF page with the text "Hello, World!" (only relevant part shown):

![Hello](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytdimkqih32jwjupmi7h.png)

What's going on here:

* `\documentclass{minimal}` defines the kind of document we're making - as we're not really interested in any typesetting, we can just use `minimal`. The most common type for actual documents would be `article`.
* then follows basically equivalent of HTML `<head>` part
* `\begin{document} ... \end{document}` is like HTML `<body> ... </body>`
* We define `\hello` command with `\newcommand\hello[1]{Hello, #1!}` - the `[1]` says it takes one argument, then in the function body `#1` refers to that argument.
* We call the function with `\hello{World}` - there are no parentheses here, we defined explicitly it takes exactly one argument.

### Loop

Let's try to setup a loop from 11 to 20. Obviously the system comes with lists already (numbered with `\begin{enumerate} \item A \item B \end{enumerate}`, bulleted with `\begin{itemize} \item A \item B \end{itemize}`, and all the other usual kinds), but we'll be doing a FizzBuzz shortly.

```latex
\documentclass{minimal}
\setlength{\parindent}{0pt}
\usepackage{ifthen}

% \numberloop{A}{B} prints all numbers from A to B
\newcommand\numberloop[2]{
  \newcounter{i}
  \setcounter{i}{#1}
  \whiledo{\not{\value{i}>#2}}
    {
      \thei
      \ifthenelse{\equal{#2}{\thei}}{.}{,}
      \stepcounter{i}
    }
}

\begin{document}
\numberloop{10}{100}
\end{document}
```

Which generates this:

![Loop](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ra56r78r6m709lflqngi.png)

What's going on:

* TeX has annoying default of having paragraph indent, we need to get rid of it with `\setlength{\parindent}{0pt}`
* we import a package called `ifthen` with `\usepackage{ifthen}` - it contains some control structures `\ifthenelse` and `\whiledo`
* `%` indicates line comments
* we define command `\numberloop` that takes two arguments
* inside it we define integer variable ("counter") `i` and set it to `#1` (first passed argument)
* there's nothing like `... <= ...` in a loop, so loop condition must be `\not{... > ...}` (or +1 one of the sides)
* inside the loop body, `\thei` means "current value of `i` counter"
* `\ifthenelse{\equal{#2}{\thei}}{.}{,}` prints appropriate separator - `,` normally, but `.` in the final iteration.
* `\stepcounter{i}` increases counter `i` by `1` each time

### FizzBuzz

```latex
\documentclass{minimal}
\setlength{\parindent}{0pt}
\usepackage{ifthen}
\usepackage{intcalc}
\usepackage{multicol}

% \fizzbuzz{N} prints Fizz, Buzz, FizzBuzz, or N, according to the usual rules
\newcommand\fizzbuzz[1]{
  \ifthenelse{\equal{\intcalcMod{#1}{15}}{0}}{FizzBuzz}{
    \ifthenelse{\equal{\intcalcMod{#1}{5}}{0}}{Buzz}{
      \ifthenelse{\equal{\intcalcMod{#1}{3}}{0}}{Fizz}{#1}
    }
  }
}

% \fizzbuzzloop{A}{B} prints all FizzBuzz entries from A to B
\newcommand\fizzbuzzloop[2]{
  \newcounter{i}
  \setcounter{i}{#1}
  \whiledo{\not{\value{i}>#2}}
    {
      \fizzbuzz{\thei}
      \linebreak
      \stepcounter{i}
    }
}

\begin{document}
\begin{multicols}{4}
\fizzbuzzloop{1}{100}
\end{multicols}
\end{document}
```

Which generates this:

![FizzBuzz](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83eerdqg7iwoxyzgucdg.png)

A few things are going on here:

* we import package for integer math `\usepackage{intcalc}`
* we import package for multi-column layout `\usepackage{multicol}`
* `\fizzbuzz{N}` does the FizzBuzz for one number
* `\fizzbuzzloop{A}{B}` does the FizzBuzz for all numbers from A to B, with line breaks in between
* we wrap it all in a 4-column layout so the screenshot looks better

### Fibonacci

```latex
\documentclass{minimal}
\setlength{\parindent}{0pt}
\usepackage{ifthen}
\usepackage{intcalc}

% \fib{N} returns the Nth Fibonacci number
\newcounter{j}
\newcounter{fiba}
\newcounter{fibb}
\newcounter{fibc}
\newcommand\fib[1]{
  \setcounter{j}{1}
  \setcounter{fiba}{1}
  \setcounter{fibb}{1}
  \whiledo{\value{j} < #1}
    {
      \setcounter{fibc}{\intcalcAdd{\thefiba}{\thefibb}}
      \setcounter{fiba}{\thefibb}
      \setcounter{fibb}{\thefibc}
      \stepcounter{j}
    }
  \thefiba
}

% \fibloop{A}{B} prints all Fibonacci numbers from A to B
\newcommand\fibloop[2]{
  \newcounter{i}
  \setcounter{i}{#1}
  \whiledo{\not{\value{i}>#2}}
    {
      \fib{\thei}
      \linebreak
      \stepcounter{i}
    }
}

\begin{document}
\raggedright
\fibloop{1}{20}
\end{document}
```

Which generates this:

![Fib](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7imy1idwofui7ktblhs2.png)

TeX has serious problems with recursion, so we do a loop calculation instead. Oh and while previous code might have implied that `\newcounter` variables are local - they are all completely global, except for `#1` etc. arguments.

### Should you use TeX?

Only if you're forced to by your journal. Otherwise no, it's completely obsolete.

Historically its primary strength was math. In particular, supporting made-up mathematical notation each researcher would come up with (the normal notation was supported by everything anyway). But nowadays, other systems can do that too. For everything else, TeX was never good.

TeX also seems to largely abandoning its existing programming language and [embedding much saner Lua instead](https://dev.to/taw/100-languages-speedrun-episode-04-lua-1ofm).

Even as an esoteric programming language, TeX's programming language doesn't really do anything too interesting. If you want a fun challenge, [writing Postscript is likely to provide a lot better one](https://dev.to/taw/100-languages-speedrun-episode-24-postscript-4i2k).

### Code

[All code examples for the series will be in this repository](https://github.com/taw/100-languages-speedrun).

[Code for the TeX episode is available here](https://github.com/taw/100-languages-speedrun/tree/master/episode-28-tex).