I am going to suffer horrendously writing this blog post without doing any Lisp jokes; Because the thing about Lisp is that it is not only a great programming language, but the best one at supporting ridiculously superior punchlines.
So, first, what's Lisp?
Lisp is a programming language that has been around for a while. It has always been there in the background. It is basically the "Path not taken", the "other option" for computing that was always around. It has always had a strong community of people that thought this option was discarded too early.
We are talking about 1958, people.
Many of you would never have heard about it, so you might ask yourself, rightfully: "Well, if this Mythical Beast has not succeeded by now, it is probably a poor idea and the path that was not taken should stay as such".
To address this, first we need to be a bit more precise. First, Lisp is not a programming language, but a whole family of programming languages. It started as a way to have a mathematical notation for software. So it could be easier to reason about software and to write software that reasons about software.
For many years we talked about Artificial Intelligence rather than Machine Learning. Lisp was a language for Artificial Intelligence. And somewhat naturally there was a natural selection of some really weird people being interested in it. Which probably turned off most others. The whole "mathematical nature" seemed contrary to an industry that is focused on "getting things done".
John McCarthy, who created it, chose a syntax that was a bit weird (thinking that, well, he'll come around to fixing the weirdness in version 2.0): Instead of using fixed width instructions, white space or line terminators (such as a newline or a semicolon) he chose to imbricate the expressions in parenthesis.
This is why the usual joke about Lisp, which I am not going to make, is about the language looking something similar to (((()(((((())(()))))))()()())).
Version 2.0 didn't really materialize and the parenthesis are with us to this day. And maybe keeping those wasn't such a bad idea. It does look quite different from any other language.
And through the years Lisp has died, every year. It even had its own hardware architecture for a time. But these are now in Museums (and without doubt in basements of the department of defense).
But every generation seems to rediscover it and its charms, and there are pockets of resistance that allow it, like a virus hidden in a ganglions, to survive generational gaps (Emacs!). There are also industrial players that have always used it (such as NASA and Boeing) which allowed for fresh generations to be exposed to it. But unlike Cobol and Algol or Fortran, Lisp stays fresh. People that discover it feel often that Lisp is an idea that could have happened now.
So what's so special about it? Lisp treats code as data. We are used to separate those, but really, code is data, right? In all other languages (that are not a Lisp that is) you write code as text. For a computer the code itself is meaningless. It's text (you can think about Ruby here, a language that tries hard to be as visually pleasing as possible, as potentially the most contrary thing to Lisp, even if some have argued that it is, by itself, an acceptable Lisp.)
So you have this "source code", and then you have either an interpreter or a compiler that will transform your code into something else, an AST (an Abstract Syntax Tree) that it will either interpret directly .. or create yet another intermediary representation (as byte-code to be itself interpreted by a virtual machine, or as object code to be run against the processor).
In Lisp, all program code is written as parenthesized lists ("s-expressions") that contain other parenthesized lists. Its parentheses all the way down. Why is this important? Because it means a Lisp program can very easily read and write Lisp code. In Lisp the AST and the code are the same. Lisp is basically the simplest form of writing an AST such as that it would still be readable by a human.
In a way Lisp is the only language in which you actually code. In other languages you write text that is transformed to code. And Lisp is a dynamic language, making Lisp an incredibly powerful tool to create very concise programs to treat a specific issue. More often than not when you write Lisp code you are writing a whole language, one that could express your problem space with elegance (DSLs, or domain specific languages). Weirdly, with all of its parentheses and its prefixed expressions, that admittedly can put off the occasional onlooker, (* 7 9)
being seven multiplied by nine, Lisp code is some of the most readable code you can find.
Lisp in 2019
As I told you Lisp is not a language but a family of languages, we call them dialects. For example the very popular HackerNews forum, is itself written in arc, a dialect of Lisp (created by Paul Graham, seemingly just for the occasion). And some dialects have become quite popular over the last few years, Clojure which is a dialect targeting the JVM has become immensely popular in data science circles. Scheme (one of the older dialects at 44 years old) has seemed to have regained some youth, Racket has been gaining traction, and now many in the Python world have started toying with Hy, a dialect of Lisp that's embedded in Python.
But for many Lisp, is Common Lisp, an ANSI standard, and it too, like its brethren (or children) is, beyond an object of curiosity, gaining interest.
... so we are happy, relieved and somewhat amused to announce the availability of Common Lisp on Platform.sh
The thing is that we do really like to eat our own dog food, and we have a couple of services written in Common Lisp. So for our own internal use we have created a run-time (it really is not that much effort). And although, we can't really say people have been banging at our doors to get proper Lisp support... we truly hope some of you will enjoy this.
How would you deploy a Lisp web application on Platform.sh?
Step 1. Write your Lisp program:
Here I created an example.lisp
with the following:
(defpackage #:example
(:use :hunchentoot :cl-who :cl)
(:export main))
(in-package #:example)
(define-easy-handler (greet :uri "/hello") (name)
(with-html-output-to-string (s) (htm (:body (:h1 "hello, " (str name))))))
(export 'main)
(defun main ()
(let ((acceptor (make-instance
'easy-acceptor
:port (parse-integer (uiop:getenv "PORT")))))
(start acceptor)
(sleep most-positive-fixnum)))
Step 2. Add an
ASDF is the "make" of Common Lisp, it is a description of dependencies between files of source code in such a way that they can be compiled and loaded in the right order.
So, create an .asd
file. If Platform.sh finds one in the repository it will do the right thing, installing a quicklisp distribution and building what needs to be built.
Here is an example.asd
file:
(defsystem example
:name "example"
:description "Example of a simple web application on Platform.sh"
:author "Lisp Coder <user@example.com>"
:components ((:file "example"))
:build-operation "asdf:program-op"
:build-pathname "example"
:entry-point "example:main"
:depends-on (:hunchentoot :cl-who))
Step 3. Add the Platform.sh
Create a .platform.app.yaml with something such as:
name: app
type: lisp:1.5
disk: 512
web:
commands:
start: ./example
Note: there are oh so many Lisps out-there, even Common Lisps. lisp:1.5
here refers to the Steel Bank Common Lisp (SBCL) version.
In .platform/routes.yaml
"https://{default}/":
type: upstream
upstream: "app:http"
And for good form create an empty .platform/services.yaml
.
Commit and push, if you visit the environment URL with /hello?name=Me!
you should see a nice greeting.
This blog post is dedicated to the true believers, kisses @ralt @cms.
λ!