DEV Community 👩‍💻👨‍💻

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

100 Languages Speedrun: Episode 28: TeX

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!

\documentclass{minimal}

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

\begin{document}
\hello{World}
\end{document}
Enter fullscreen mode Exit fullscreen mode

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

Hello

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.

\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}
Enter fullscreen mode Exit fullscreen mode

Which generates this:

Loop

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

\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}
Enter fullscreen mode Exit fullscreen mode

Which generates this:

FizzBuzz

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

\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}
Enter fullscreen mode Exit fullscreen mode

Which generates this:

Fib

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.

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.

Code

All code examples for the series will be in this repository.

Code for the TeX episode is available here.

Top comments (1)

Collapse
 
marcellourbani profile image
Marcello Urbani

I think you're wrong about obsolescence
Well, half wrong.
It's as old as it gets and was painful even first time I saw it 30 years ago.
But nothing better came along for scientific typesetting, and it's still widely used in academia

12 APIs That You Will Love

>> Check out this classic DEV post <<