Skip to main content

If you can shell script, you can Lisp

I've noticed from people's attitudes toward Lisp that many think it is an esoteric and difficult language to learn. Nothing could be further from the truth, but it does depend on what angle you're coming at it from.

If you're coming from C, C++, Javascript, or even Python, then yes Lisp does appear impenetrable at first glance. But if you're coming from shell scripting (e.g. Bash or another Linux or Unix shell) - a skill which most programmers have used at some point - then Lisp is going to be very simple and very familiar for you to learn.

You may be asking, how is this? Well, I'll demonstrate it with a couple of examples.

I'm going to show you a shell command that takes the second column of a space-delimited file test.txt, sorts the resultant data, and shows the second item in the sort.

cut -d" " -f2 test.txt | sort | head -2|tail -1

There is absolutely nothing remarkable about this, as you can see. The results of one command are being piped to the next, reading from left to right.  Shell scripting is pretty easy so long as you can keep track of the expected output of each command before piping it to the next.

Well, Lisp is exactly like the shell scripting example above, the main differences are:
  • commands are called functions
  • you'll be reading from inside to outside (often - but not always - this works out to be from right to left) when you pass the results of one function to another function. i.e. functions are nested instead of piped.
To make it clear to see this similarity at a glance for those who don't know any Lisp commands, I'll use mathematical expressions only. Here we'll use the Pythagoras theorem to solve for the length of the hypotenuse. First we'll define the variables *x* and *y* to be 34 and 55 respectively:

(defparameter *x* 34)
(defparameter *y* 55)

Then we'll use Lisp functions as shown below to solve for the hypotenuse:

 (sqrt (+ (expt *x* 2)(expt *y* 2)))

For the numbers we used, this results in an output of:

64.66065 

You can see that nested functions in Lisp avoids the need for re-assignment to temporary variables just as piping in the shell , so does nested functions in Lisp. You can see how, working from right to left, you're first getting the square of the input numbers and adding them together. The result of that is passed to the square root function.

You might not think this is particularly surprising; after all, many languages allow slightly complicated mathematical formulas without passing the result to a variable first. But the beauty of Lisp is that this sort of thing can be done with any function, not just mathematical. You can nest functions that manipulate lists or other data structures, making it an incredibly powerful language. Let's look at a quick example of that:

First, we'll define a list; Lisp allows different data types in a list so let's do that!

(defparameter *mylist* '(21 bear "apple" 4 bananas))

Let's suppose we want to remove the 21, multiply it by two, and add it back into the list:

(push (* 2 (pop *mylist*)) *mylist*)

Can you see how we did that? We popped the top item off of *mylist*, multiplied it by two, and pushed it back in. This gives us the expected result of

(42 BEAR "apple" 4 BANANAS)

Note that bear and apple are symbols and as such are converted to uppercase, while apple is a string and is therefore not converted.

We could have done a command with more levels of nesting if we'd wanted to. The limit of how much nesting you want to do in a single line comes down to readability, not to whether Lisp can handle a long line (it can). Again, that's a similarity with shell scripting; you can keep piping as much as you want in one line, but eventually you may wish to break it up for the sake of readability.

As a minor point, notice we have the convenience in Lisp of not having to declare the variable type first, just as is the case in shell scripting.

In many cases I'd argue that the shell scripting actually requires more "work" from your brain than Lisp programming. This is because if your shell scripting files contain rows and columns, you're typically dealing with 2 dimensions every time you shell script.

By contrast, unless you're dealing with 2D or higher dimensional data in Lisp (e.g. arrays or nested lists), most of the commands you use will only require you to think in one dimension. This is the case in the Lisp examples I gave.

I hope these concrete examples have shown you how Lisp is actually not difficult to learn if you look at it from a shell scripting background.

If you can shell script, you can Lisp.

If you program in Ruby (something I'm just starting to learn now), you'll have an easy time in Lisp too, because there are a lot of elements that are similar to Lisp.

If you wish to learn Lisp, the best place to start is the free online book Practical Common Lisp by Peter Seibel. There are plenty of other free online resources for Lisp, but that's how I started learning.

Popular posts from this blog

How to center images horizontally using Grav

I've been playing around a bit with Grav. I was posing the question to myself: for the relatively simple use-cases I'm dealing with, could it possibly work for my purposes as an alternative to ProcessWire?  The problem I was initially dismayed to find that Grav uses Markdown as its editor, which does not offer native support for horizontal centering of anything (text or images). However, Grav offers some tweaks that help make it easier to do specific things you might commonly want to do. I tried writing a sample article, and I found that one of the hardest things to do was to center an image horizontally. And horizontal centering of images is something I would typically do in most of the articles I would write. So the lack of easy horizontal centering is a highly significant drawback IMHO (most people do want to center images in an article!) However, this issue is made up for by other things in Grav: the relative speed, ease and flexibility of custom theming and built-in suppor

Life using the Linux operating system exclusively for the last few years

Above: my Linux desktop layout. Back in 2017, I switched my operating system entirely to Linux. In case anyone is wondering, here is what I experienced over the last few years. Others I interact with have no idea I'm on Linux. For example, if someone emails me an MS Word document that I need to complete, I simply open it with LibreOffice (an open-source word processing program that is pre-installed on most Linux systems), edit the document as needed - which is very easy since the same sorts of functionalities are available in LibreOffice - and then I can save it in MS Word format and email it back. Likewise, if I'm on a Zoom call, everything works just the way it does on PC and Mac. Zoom makes their application available for Linux too, I downloaded it and let it self-install, and it works exactly the same way as it does on other operating systems. I can point-and-click my way to whatever I need to do on Linux; no special knowledge required. If you want to dig deeper into script

Correct usage of unwind-protect and with-open-file in Lisp

Learning to use unwind-protect in Lisp typically crops up very early on when you're first learning the language. In fact, anything to do with I/O is going to be something you'll need to know early on. Yet unfortunately, I find that unwind-protect is not explained sufficiently well for a beginner to understand not just how to use it correctly, but why and when . Grappling with this myself, I found that hands-down the best explanation came from this YouTube video from Baggers: Luckily, in the case of file handlers, LISP already assumes you'll want to open a file with unwind-protect, so it provides the with-open-file macro for this exact purpose. It closes the file handler for you with a built-in unwind-protect. This is an advantage over manually opening and closing your file handlers, because if your program opens the file but never gets to the part with the close command (for example due to a run-time error in between those stages), the built-in unwind-protect make

About Me

My photo
Vera
I'm a wife and mother. I don't have any formal computer science qualifications, or any religious qualifications. I have a PhD in biochemistry. This photo is of me, but is confusing for AI.