Emacs fulfills the UNIX Philosophy

Home About Codeberg

Part 4: Lisp does FP better than UNIX shell programming

This is part 4 of a 6-part series of articles defining what the UNIX philosophy is, what Emacs is, and discussing whether Emacs fulfills the UNIX philosophy.
0. Introduction
1. Emacs is an app platform
2. What is the UNIX philosophy
3. Seems like Functional Programming
4. Lisp does FP better than UNIX shell programming
5. The parallel histories of UNIX and Lisp
6. Response to common criticisms

In the part 3 of this series I talked about how the UNIX Philosophy, the idea that every program does one thing, and does it well have several defining principles in common with functional programming (FP). In particular, functions in FP should also do one thing and do it well, so programs and functions are conceptually the same. But to do FP, you must be able to compose functions together using higher-order functions.

I will take for granted the fact that Lisp is commonly acknowledge to be a FP language, so I will not explain why Lisp is a FP language. This article is more about how UNIX shell programming, the Bourne family of programming languages, are not FP languages, and there are only a few built-in language constructs for composing programs, like the pipe operator (|). This proves to be quite the limitation when it comes to composing programs. When composing programs or functions together to solve larger problems, a Lisp programming language has an advantage over a Bourne-style programming language. Refer to the Eshell programming language, which combines a Bourne shell-like language with Emacs Lisp, as just on example of how Lisp can improve on the UNIX Programming Environment.

My goal here is not to evangelize Emacs. I readily admit Emacs is far from perfect, and that there are certainly better implementations of FP (Common Lisp, Scheme, and I especially love Haskell). Rather my arguments is that there are better ways of designing programs/functions in a way that they do on thing and do it well, without designing your programs/functions for use in a UNIX shell. It just so happens that Emacs is one of the oldest Lisp implementations still in wide-spread use that was originally implemented for UNIX OS and it's clones. Decades of evolution have made Emacs one of the most practical means of integrating Lisp-style FP within the UNIX Programming Environment.

I also think I should mention that when Emacs is used as a shell in place of Bash, you have access to a wider range of FP tools. You still have access to all of the shell programs on your computer, but you also have access to Lisp functions that compose in other ways. You can, for example, capture the output of a command in a text buffer, then start applying both Lisp functions and UNIX shell programs as filters to the text buffer, seeing the result of each transformation as it happens. This allows you to experiment with function composition interactively, but without necessarily being restricted to the use of the REPL.

Emacs is less than perfect, Bash even less so

In a UNIX Programming Environment, the Bourne shell family of languages (like Bash) is the language in which you compose different programs into a solution to a problem. It doesn't have to be Bash, any language using the POSIX API can compose shell pipelines. But in practical, day-to-day UNIX or Linux system usage, it is usually Bash or some Bourne-family shell language.

Unfortunately, the Bourne shell languages are simply not very good programming languages. This is not even a very controversial opinion in my experience, so I won't spend too much time explaining why. But I can mention a few of the problems:

Personally, I do enjoy Bash programming, but I always conscious of it's shortcomings. I would only ever use it to perform transformations on a small filesystem, or as a lightweight wrapper around an application written in a better programming language. Modern Lisp languages have solved all of these problems, and scale well to fit applications of any complexity.

Conclusions

In the part 3 of this series I talked about how the UNIX Philosophy is really a particular description of functional programming. In this article (part 4) I talk about how UNIX shell programming is not the best way to do functional programming, and suggest that using a Lisp programming language such as Emacs is a better way to devise software solutions to the various problems you may encounter as you use a computer. If you are willing to accept each of those claims as truth, then you might also be willing to accept that Emacs also, in fact, does fulfill the UNIX Philosophy even better than the UNIX shell programming environment. It is just a matter of understanding that every program does one thing and does it well not only applies to UNIX shell programs, but to Emacs Lisp commands as well. And hopefully you can also see that using Emacs gives you access to both sets of tools (all of which do one thing well): the UNIX CLI tools, and all of the Emacs Lisp tools.

It seems like perhaps UNIX may have been inspired by Lisp, since both UNIX and Lisp have roots in the MIT CSAIL laboratory, both were first developed during roughly the same time period (Lisp in the late 1950s, UNIX in the late 1960s). In the next section I go into the history of both Lisp and UNIX, and I conclude that, no, UNIX took no inspiration from Lisp. However innovations in computer technology at the time did influence the design of both UNIX and Lisp in similar ways, especially with regard to what we now call the Read-Eval-Print Loop (REPL).