> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# We are happy, relieved and somewhat amused to announce the availability of Common Lisp on Platform.sh

> Discover the history and uniqueness of Lisp, a programming language often called 'the path not taken,' and learn how to deploy a Lisp web applications.

export const PostMeta = ({data = {}}) => {
  const {author, date, image} = data;
  const authors = Array.isArray(author) ? author : author ? [author] : [];
  const resolveAuthor = slug => {
    const entry = AUTHOR_MAP[slug] || ({});
    const name = entry.name || slug;
    const github = entry.github || null;
    const linkedin = entry.linkedin || null;
    const url = github ? `https://github.com/${github}` : linkedin || null;
    const avatarUrl = github ? `https://github.com/${github}.png?size=64` : null;
    return {
      name,
      url,
      avatarUrl
    };
  };
  const formattedDate = date ? new Date(date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }) : null;
  if (!image && authors.length === 0 && !formattedDate) return null;
  const AUTHOR_MAP = {
    "aaron-collier": {
      "name": "Aaron Collier"
    },
    "aaron-dudenhofer": {
      "name": "Aaron Dudenhofer"
    },
    "aaron-porter": {
      "name": "Aaron Porter"
    },
    "adriaan-odendaal": {
      "name": "Adriaan Odendaal"
    },
    "ajmal": {
      "name": "Ajmal Siddiqui"
    },
    "akalipetis": {
      "name": "Antonis Kalipetis"
    },
    "alexander-varwijk": {
      "name": "Alexander Varwijk"
    },
    "alicia-bevilacqua": {
      "name": "Alicia Bevilacqua"
    },
    "amelie-deguerry": {
      "name": "Amelie Deguerry"
    },
    "anacidre": {
      "name": "Ana Cidre",
      "linkedin": "https://www.linkedin.com/in/ana-cidre"
    },
    "andoni": {
      "name": "Andoni Auzmendi"
    },
    "andrei-taranu": {
      "name": "Andrei (Alex) Taranu",
      "linkedin": "https://www.linkedin.com/in/andrei-alex-taranu/"
    },
    "andrew-baxter": {
      "name": "Andrew Baxter"
    },
    "andrew-melck": {
      "name": "Andrew Melck"
    },
    "antoine-crochet-damais": {
      "name": "Antoine Crochet Damais"
    },
    "augustin-delaporte": {
      "name": "Augustin Delaporte",
      "linkedin": "https://www.linkedin.com/in/augustindelaporte/"
    },
    "branislav-bujisic": {
      "name": "Branislav Bujisic"
    },
    "carl-smith": {
      "name": "Carl Smith"
    },
    "caroline-leroy": {
      "name": "Caroline Leroy"
    },
    "cati-mayer": {
      "name": "Cati Mayer"
    },
    "catplat": {
      "name": "C Trinkwon"
    },
    "ceelolulu": {
      "name": "Celeste van der Watt"
    },
    "chadwcarlson": {
      "name": "Chad Carlson",
      "github": "chadwcarlson",
      "linkedin": "https://www.linkedin.com/in/chadwcarlson"
    },
    "chris-ward": {
      "name": "Chris Ward"
    },
    "chris-yates": {
      "name": "Chris Yates"
    },
    "christian-sieber": {
      "name": "Christian Sieber"
    },
    "christopher-lockheardt": {
      "name": "Christopher Lockheardt"
    },
    "christopher-skene": {
      "name": "Christopher Skene"
    },
    "chuck-morgan": {
      "name": "Chuck Morgan"
    },
    "corey-dockendorf": {
      "name": "Corey Dockendorf"
    },
    "crell": {
      "name": "Crell"
    },
    "damz": {
      "name": "Damz"
    },
    "dan-morrison": {
      "name": "Dan Morrison"
    },
    "davidbonachera": {
      "name": "David Bonachera",
      "github": "davidbonachera",
      "linkedin": "https://www.linkedin.com/in/davidbonachera"
    },
    "dereliahmet1": {
      "name": "Ahmet Faruk Dereli"
    },
    "devicezero": {
      "name": "Jonas Kröger",
      "github": "devicezero",
      "linkedin": "https://www.linkedin.com/in/jonaskroeger/"
    },
    "doug-goldberg": {
      "name": "Doug Goldberg"
    },
    "duncan-naves": {
      "name": "Duncan Naves",
      "github": "duncannaves",
      "linkedin": "https://www.linkedin.com/in/duncan-naves-a94423aa"
    },
    "erika-bustamante": {
      "name": "Erika Bustamante"
    },
    "fabpot": {
      "name": "Fabien Potencier"
    },
    "flovntp": {
      "name": "Florent Huck",
      "github": "flovntp",
      "linkedin": "https://www.linkedin.com/in/florenthuck"
    },
    "fred-plais": {
      "name": "Fred Plais"
    },
    "gauthier-garnier": {
      "name": "Gauthier Garnier"
    },
    "gilzow": {
      "name": "Paul Gilzow"
    },
    "gmoigneu": {
      "name": "Guillaume Moigneu",
      "github": "gmoigneu",
      "linkedin": "https://www.linkedin.com/in/guillaumemoigneu/"
    },
    "gregqualls": {
      "name": "Greg Qualls"
    },
    "guguss": {
      "name": "Augustin Delaporte"
    },
    "haylee-millar": {
      "name": "Haylee Millar"
    },
    "ivana-kotur": {
      "name": "Ivana Kotur"
    },
    "jackrabbithanna": {
      "name": "Mark Hanna"
    },
    "jared-wright": {
      "name": "Jared Wright",
      "github": "jww-sh",
      "linkedin": "https://www.linkedin.com/in/jaredwaynewright"
    },
    "jessica-orozco": {
      "name": "Jessica Orozco"
    },
    "joey-stanford": {
      "name": "Joey Stanford"
    },
    "john-grubb": {
      "name": "John Grubb"
    },
    "jonas-kruger": {
      "name": "Jonas Kruger"
    },
    "kathryn-frazer": {
      "name": "Kathryn Frazer"
    },
    "kemiojo": {
      "name": "Kemi Elizabeth Ojogbede"
    },
    "kieronsambrook-smith": {
      "name": "Kieronsambrook Smith"
    },
    "laurent-arnoud": {
      "name": "Laurent Arnoud"
    },
    "letoya-boyne": {
      "name": "Letoya Boyne"
    },
    "lolautruche": {
      "name": "Jérôme Vieilledent"
    },
    "lyly-lepinay": {
      "name": "Lyly Lepinay"
    },
    "manauwar-alam": {
      "name": "Manauwar Alam"
    },
    "marc-antoine-porri": {
      "name": "Marc Antoine Porri"
    },
    "maria-antinkaapo": {
      "name": "Maria Antinkaapo"
    },
    "maria-de-anton": {
      "name": "Maria De Anton"
    },
    "mark-dorison": {
      "name": "Mark Dorison"
    },
    "markus-hausammann": {
      "name": "Markus Hausammann"
    },
    "mary-thomas": {
      "name": "Mary Thomas"
    },
    "mathias-bolt-lesniak": {
      "name": "Mathias Bolt Lesniak"
    },
    "mathieu-strauch": {
      "name": "Mathieu Strauch"
    },
    "matthias-van-woensel": {
      "name": "Matthias Van Woensel",
      "linkedin": "https://www.linkedin.com/in/matthias-van-woensel-267a069"
    },
    "michael-sharp": {
      "name": "Michael Sharp"
    },
    "mupsi": {
      "name": "Marine Gandy"
    },
    "natalie-harper": {
      "name": "Natalie Harper"
    },
    "ngommenginger": {
      "name": "Nicolas Gommenginger",
      "linkedin": "https://www.linkedin.com/in/nicolas-gommenginger"
    },
    "nicholas-bennison": {
      "name": "Nicholas Bennison"
    },
    "nicholas-vahalik": {
      "name": "Nicholas Vahalik"
    },
    "nick-hardiman": {
      "name": "Nick Hardiman"
    },
    "nickanderegg": {
      "name": "Nickanderegg"
    },
    "nicolas-grekas": {
      "name": "Nicolas Grekas",
      "github": "nicolas-grekas",
      "linkedin": "https://www.linkedin.com/in/nicolasgrekas/"
    },
    "niti-malwade": {
      "name": "Niti Malwade"
    },
    "opensocialteam": {
      "name": "Opensocialteam"
    },
    "ori-pekelman": {
      "name": "Ori Pekelman"
    },
    "otavio-santana": {
      "name": "Otavio Santana"
    },
    "palwandi": {
      "name": "Pawan Alwandi",
      "github": "pawpy",
      "linkedin": "https://www.linkedin.com/in/pawanalwandi"
    },
    "patrick-boest": {
      "name": "Patrick Boest"
    },
    "patrick-dawkins": {
      "name": "Patrick Dawkins",
      "github": "pjcdawkins",
      "linkedin": "https://www.linkedin.com/in/patrickdawkins"
    },
    "patrick-klima": {
      "name": "Patrick Klima"
    },
    "pjcdawkins": {
      "name": "Pjcdawkins"
    },
    "prineet-kaurbhurji": {
      "name": "Prineet Kaurbhurji"
    },
    "quentin-sinig": {
      "name": "Quentin Sinig"
    },
    "ralt": {
      "name": "Florian Margaine",
      "github": "ralt",
      "linkedin": "https://www.linkedin.com/in/florian-margaine-43971136"
    },
    "ramanathanramakrishnamurthy": {
      "name": "Ramanathanramakrishnamurthy"
    },
    "remi-lejeune": {
      "name": "Rémi Lejeune"
    },
    "ribel": {
      "name": "Taras Kruts"
    },
    "robert-douglass": {
      "name": "Robert Douglass"
    },
    "rudy-weber": {
      "name": "Rudy Weber"
    },
    "ryan-hicks": {
      "name": "Ryan Hicks"
    },
    "sabri-helal": {
      "name": "Sabri Helal"
    },
    "savannah-bergeron": {
      "name": "Savannah Bergeron"
    },
    "shannon-vettes": {
      "name": "Shannon Vettes"
    },
    "shawn-ogasawara": {
      "name": "Shawn Ogasawara",
      "linkedin": "https://www.linkedin.com/in/shawn-ogasawara-83a9a0/"
    },
    "shawna-spoor": {
      "name": "Shawna Spoor"
    },
    "shedrack-akintayo": {
      "name": "Shedrack Akintayo"
    },
    "simon-ruggier": {
      "name": "Simon Ruggier"
    },
    "sophie-van-der-kindere": {
      "name": "Sophie Van Der Kindere"
    },
    "stefanos-thampis": {
      "name": "Stefanos Thampis"
    },
    "stephen-weinberg": {
      "name": "Stephen Weinberg"
    },
    "sukhman-virk": {
      "name": "Sukhman Virk"
    },
    "sumaira-nazir": {
      "name": "Sumaira Nazir"
    },
    "sumer": {
      "name": "Sümer Cip"
    },
    "syed-raza": {
      "name": "Syed Raza"
    },
    "tamara-bacchia": {
      "name": "Tamara Bacchia"
    },
    "tara-arnold": {
      "name": "Tara Arnold"
    },
    "theosakamg": {
      "name": "Mickael Gaillard",
      "github": "theosakamg"
    },
    "thomasdiluccio": {
      "name": "Thomas di Luccio"
    },
    "tim-anderson": {
      "name": "Tim Anderson"
    },
    "tom-helmer-hansen": {
      "name": "Tom Helmer Hansen"
    },
    "tylermills": {
      "name": "Tyler Mills"
    },
    "upsun": {
      "name": "Upsun"
    },
    "veronika-tolkachova": {
      "name": "Veronika Tolkachova",
      "linkedin": "https://www.linkedin.com/in/veronika-tolkachova-169167a2"
    },
    "vince-parker": {
      "name": "Vince Parker"
    },
    "vinnie-russo": {
      "name": "Vincenzo Russo"
    },
    "vrobert78": {
      "name": "Vincent Robert",
      "github": "vrobert78",
      "linkedin": "https://www.linkedin.com/in/vincent-robert-498a883"
    },
    "yuriy-babenko": {
      "name": "Yuriy Babenko"
    },
    "yuriy-gerasimov": {
      "name": "Yuriy Gerasimov"
    }
  };
  return <div className="post-meta">
      {(authors.length > 0 || formattedDate) && <div className="post-meta-info">
          {authors.length > 0 && <div className="post-meta-authors">
              {authors.map(slug => {
    const {name, url, avatarUrl} = resolveAuthor(slug);
    const inner = <>
                    {avatarUrl && <img src={avatarUrl} alt={name} className="post-meta-avatar" />}
                    <span className="post-meta-author-name">{name}</span>
                  </>;
    return url ? <a key={slug} href={url} target="_blank" rel="noopener noreferrer" className="post-meta-author">
                    {inner}
                  </a> : <span key={slug} className="post-meta-author">{inner}</span>;
  })}
            </div>}
          {authors.length > 0 && formattedDate && <span className="post-meta-separator" aria-hidden="true">·</span>}
          {formattedDate && <span className="post-meta-date">{formattedDate}</span>}
        </div>}
      {image && <img src={image} alt="" className="post-meta-image" aria-hidden="true" />}
    </div>;
};

<PostMeta data={{ author: ["oripekelman"], date: "2019-08-08", image: "/images/posts/unknown/lisp/blog-lisp-blog.webp" }} />

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 parentheses.

<img src="https://mintcdn.com/upsun-c9761871/XkTGutbb3_ExMu0d/images/posts/unknown/lisp/john_mccarthy.webp?fit=max&auto=format&n=XkTGutbb3_ExMu0d&q=85&s=83469ae03ebefdb907f1417b7c8ffe70" alt="John McCarthy looking like a boss. Photo by Chuck Painter, circa 1974" width="1200" height="565" data-path="images/posts/unknown/lisp/john_mccarthy.webp" />

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.

> "One can even conjecture that Lisp owes its survival specifically to the fact that its programs are lists, which everyone, including me, has regarded as a disadvantage."
>
> John McCarthy, "History of Lisp", 1979

And through the years Lisp has died, every year. It even had its own
[hardware architecture](https://en.wikipedia.org/wiki/Lisp_machine) 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.

> "Lisp has jokingly been called "the most intelligent way to misuse a computer." I think that description is a great
> compliment because it transmits the full flavor of liberation: it has assisted a number of our most gifted fellow
> humans in thinking previously impossible thoughts."
>
> * Edsger Dijkstra, The Humble Programmer, 1972

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](https://news.ycombinator.com/) 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](https://github.com/hylang/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:

```lisp {filename="example.lisp"} theme={null}
(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)))
```

> (This code is quite surprisingly legible, "use" means "import all the symbols so that I don't have to prefix them with
> the package name", 'hunchentoot' is a web server in Lisp (you can also notice how we get the `PORT` from the
> environment, cl-who allows us to create the actual HTML )) (and this is the only Lisp joke I am doing, it is subtle
> (right?))

### Step 2. Add an `.asd` file

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:

```asd {filename="example.asd"} theme={null}
(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 `.yaml` files

Create a `.platform.app.yaml` with something such as:

```yaml {filename=".platform.app.yaml"} theme={null}
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`

```yaml {filename=".platform.app.yaml"} theme={null}
"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.

Visit our [Lisp documentation](https://docs.platform.sh/languages/lisp.html) page to learn even more.

***

This blog post is dedicated to the true believers, kisses @ralt @cms.

λ!
