Development Environments: LISP Programming Setup
Image credits: Image created by the author using the program Spectacle.
Requirements
The requirements to start programming activities with LISP are similar to those described for JavaScript, Python, and Lua: a text editor and an interpreter, or an Integrated Development Environment (IDE).
To avoid repeating the discussions from JavaScript and Python:
- If you already have a text editor, you can install a LISP interpreter to start programming using the language;
- If you would rather use an IDE, the simplest option is choosing Emacs with SLIME using Portacle, which includes a text editor, interpreter and debugger among other features;
- If you do now know how to install program, what is
PATH
or how to configure it, you can refer the topic regarding how to install programs.
Part of the contents of this page will be identical to the Python's page. Therefore, if certain paragraphs seem familiar, it will not an impression, but déjà vu. As a matter of fact, this will also occur in new entries about development environments for other programming languages. After all, the setup procedures are similar.
LISP as the First Programming Language
Python and Lua lead my list of recommended programming languages for beginners, as previously commented in introduction about development environments; the third option is JavaScript, due to the Internet.LISP can be a good language for the first programming activities, though it depends on the person. In particular, people who know the lambda calculus (λ-calculus) will probably find many resemblances between LISP and it. In fact, the λ-calculus was one of the inspirations for the first LISP implementations.
Moreover, there are multiple dialects for the LISP language.
In this page, I use Common LISP.
For beginner programmers, Racket (using DrRacket as IDE), or Scheme (also using DrRacket
, that, by the way, was originally named DrScheme) can be simpler options than Common LISP.
Another possibility is Clojure (using an IDE such as Nightcode, Lightmod, Light Table, or Cursive).
One of LISP benefits is that its syntax is simple, though the language itself is conceptually complex. It is true that LISP's syntax is different from virtually every other programming language, though this is not a problem for beginners (for they have not gotten experienced other languages).
As it is functional language, LISP also resembles more of school Mathematics than other programming languages.
On the other hand, LISP expressions are written using prefix format (notation), with operators before operands.
For instance, instead of (infix notation), the expression is written as (+ 1 (- 2 3))
.
About LISP
LISP (or Lisp, using modern spelling) is, simultaneously, a very simple and very complex language. The previous statement is contradictory, though the language requires experience and practice to explore its potential.
LISP is a functional programming language. This first characteristic makes it different from every other programming language presented in previous topics. The difference is not only regarding the parenthesis, that is immediately observable in LISP source code.
A different way of thinking is required to program in LISP. In LISP, almost everything are expressions (known as s-expressions or sexp). A program is a combination of expressions. Expressions can also result from combinations of other expressions.
As a first consequence, LISP does not distinguish code from data. Code and data are expressions. Code can be data; data can be code. As a second consequence, if code and data are interchangeable, then it is possible to change code in the same way that it is possible to modify data in a program. The third consequence is that LISP enables programmers to change programmers and the language itself. In particular, it is even possible to change a LISP program while it is running.
In other words, LISP is a programmable programming language. While most programming languages allow people to create programs, LISP allows modifying (adapting) the language itself to support solving problems.
A practical application is using LISP to define Domain-Specific Languages (DSLs).
The language also supports symbolic processing.
In fact, the s
character in s-expression means symbolic (in other words, symbolic expression).
This makes the language a good choice for Artificial Intelligence (AI) research.
Outside Computer Science, LISP is used by some Computer Aided Design systems. An example is AutoCAD, which allows using LISP for scripting.
In the past, LISP machines provided specialized hardware to run LISP. Although these machines have been since disappeared, it may be interesting to know about them to discover forgotten paths for programming.
Nowadays, GNU Emacs remains as an example of LISP's adaptability potential. Indeed, Emacs is one of the best IDEs for LISP (the text editor does, in fact, work as a LISP IDE).
For LISP documentation, one can refer to:
- The documentation provided the function
describe()
. For instance,(describe 'string/=)
; - The Common Lisp HyperSpec, from LispWorks;
- GNU Emacs Manual. Although the material does not apply to all LISP dialects, many functions and macros are similar.
Versions and Dialects
LISP is an old language, with several branchings. Thus, it is necessary to choose a dialect to program in LISP (or another derived language). LISP can be interpreted or compiled, depending on the use and/or the chosen dialect.
As previously mentioned in LISP as the First Programming Language, some dialects can be simpler and more accessible for beginners.
This page adopts Common LISP (CL) for examples and interpreters (or compilers). Some options for Common LISP interpreters/compilers include:
- Steel Bank Common Lisp (SBCL);
- GNU CLISP;
- Clozure CL (CCL);
- Armed Bear Common Lisp;
- Allegro CL;
- LispWorks;
- Embeddable Common-Lisp (ECL), to use LISP for scripting in other programming languages.
Any option is valid to learn LISP programming. However, some are paid options (such as Allegro CL). Thus, SBCL, CLISP, CCL and LispWorks (Personal Edition) are good choices to start using the language. ECL is normally used as an interpreter embedded in a program written using other programming language (something that can also be explored using Lua and Python); thus, it is a more complex option for beginners.
Additional Remarks
The remainder of this text assumes the use of Common LISP and SBCL, though the examples may work with other options. Furthermore, some examples do not present the most idiomatic forms to program in LISP. To avoid introducing complex concepts, some (for instance, loops) are closer to procedural than to functional code.
Interpreter and Text Editor
You should use root
or administrator
accounts only to install the interpreter.
After the installation, use a regular user account, with lower privileges, to run the interpreter and program using it.
Linux
Linux's distributions commonly offer different Common Lisp implementations, such as SBCL, CLISP, CCL and ECL.
- Arch Linux:
pacman -S sbcl
- Debian, Ubuntu or distributions based on the former ones:
apt-get install sbcl
- Fedora:
dnf install sbcl
- Gentoo:
emerge --ask dev-lisp/asdf emerge --ask dev-lisp/sbcl
macOS
On macOS environments, you can use brew
to install SBCL.
Windows
To get the installer for Steel Bank Common Lisp (SBCL), you should access the downloads page and choose the option for Windows. For 32-bit systems, you must pick X86. For 64-bit systems, you can pick AMD64 (this applies both to AMD and Intel processors; AMD64 is the name of the 64-bit architecture).
When this page was written, the latest version was 2.1.9 newest
.
After the installation, the sbcl
command should be available in the PATH
.
To test it, start a terminal session on cmd
, type sbcl
, then press enter
.
If it does not work, it is possible to run the interpreter from the Start menu.
To do this, you should search for sbcl
.
Should you wish to add the interpreter to the PATH
, refer to how to install programs.
Alternatives to install the interpreter on Windows include:
- Scoop;
- An IDE with an integrated interpreter (for instance, Emacs with SLIME using Portacle).
Environment Test
You can start to program in Common LISP after installing the interpreter.
To start the interpreter, with use the downloaded executable or type sbcl
followed by enter
in a command line interpreter (this requires PATH
configuration for files manually downloaded).
sbclThis is SBCL 2.1.9, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
*
This section presents the same examples used in JavaScript and Python for purposes of testing and comparing the languages.
As in Python, you will type your code after the asterisk (*
).
For instance, you can write on the console with print()
(documentation).
To write a message, type something like (princ "Hello! My name is Franco.")
after the greater than symbols and press enter
.
The interpreter will write Hello! My name is Franco
and will wait your next command.
sbclThis is SBCL 2.1.9, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (princ "Hello! My name is Franco.")Hello! My name is Franco.
"Hello! My name is Franco"
*
The text in the images are from the Portuguese version of this page.
From now on, you should follow the previous steps whenever you read a Common LISP source code block in this page and wish to manually run in the interpreter.
To exit the interpreter, type (exit)
followed by enter
or press Ctrl d
.
On Windows, the shortcut can be Ctrl z
followed by enter
(or it may work not, requiring the use of (exit)
).
Like Python, LISP can be used in a Read, Eval, Print, Loop (REPL) mode.
(+ 1 1)
You can also type a string directly:
"Hello! My name is Franco."
However, you should note that, as in Python, those direct uses are only possible for interactive use, that is, in REPL style.
They are convenient ways to inspect values and variables, though they are not permitted in programs.
If you wish to perform the same operations in a source code file (a script), you should use princ()
to write the results.
(princ (+ 1 1))
(princ "Hello! My name is Franco.")
Thus, it can be convenient to create the habit of using princ()
when you want to write in the console.
For instance, create a file called script.lisp
(you can choose any name that you want) with the following contents:
(princ "My First Lisp Script")
(terpri)
(princ "Hello! My name is Franco.")
(terpri)
(princ "The interpreter can do Math.")
(terpri)
(princ "Check it out: ")
(princ (+ 1 1))
(terpri)
(princ "Bye!")
(terpri)
The script introduces a new function called terpri()
(documentation), that inserts a line break.
To run the script, open a command line interpreter (shell) in the directory that you have created the file and type sbcl --script script.lisp
.
The LISP interpreter will run the file provided as a parameter (the value script.lisp
after sbcl --script
) and will show results from princ()
calls.
sbcl --script script.lispMy First Lisp Script
Hello! My name is Franco.
The interpreter can do Math.
Check it out: 2
Bye!
If the current directory of command line interpreter (shell) is not the directory of the file, you can change directory to the file's folder, or you can write the absolute path of the file.
Examples for absolute file paths can include C:\Users\Franco\Desktop\script.lisp
on Windows for a file in the desktop of a user account named Franco
or ~/Desktop/script.lisp
for a file in the desktop of a Linux machine.
It can be inconvenient to write terpri()
every time that you want to add a line break.
The format()
(documentation) function is an alternative.
(format t "My First Lisp Script~%")
(format t "Hello! My name is Franco.~%")
(format t "The interpreter can do Math.~%")
(format t "Check it out: ~d~%" (+ 1 1))
(format t "Bye!")
(terpri)
In this case, ~%
inserts a line break, while ~d
allows writing an integer number calculated as the result of an expression.
If you wish, you can change the last line to (format t "Bye!~%")
.
The other examples will alternate between using princ()
and format()
.
Finally, it is useful to know it is possible to refer to a function's documentation using the REPL.
To do that, you can use the function describe()
.
(describe 'format)COMMON-LISP:FORMAT
[symbol]
FORMAT names a compiled function:
Lambda-list: (DESTINATION CONTROL-STRING &REST FORMAT-ARGUMENTS)
Declared type: (FUNCTION
((OR STRING BOOLEAN STREAM) (OR STRING FUNCTION)
&REST T)
(VALUES (OR STRING NULL) &OPTIONAL))
Derived type: (FUNCTION (T T &REST T) *)
Documentation:
Provides various facilities for formatting output.
(...)
It is enough to know how to use the REPL and run a LISP source code file for learning activities. In general, these two operations are also enough for most daily or professional uses of the programming language.
IDEs
The same considerations about the use of IDEs in Python apply to LISP. The convenience, especially for beginners, continues to be a benefit from using IDEs.
The option to run code with a single click also applies to LISP.
In particular, search for the option to run a project with a single click (normally on a triangle icon (🢒
) commonly used to play content eletroelectronics) or with a key press (usually F5
).
Furthermore, remember shortcuts for text editors, such as Ctrl n
(or File / New
) to create new files and Ctrl o
(or File / Open
) to open existing files.
Emacs with SLIME
The text editor GNU Emacs has been previously introduced. In particular, Emacs is the text editor that I use (this page was written using it).
Although I do not recommend Emacs as an option for beginners, the text editor is one of the best options to program LISP. The combination of Emacs with Superior Lisp Interaction Mode for Emacs SLIME, and a LISP interpreter/compiler is excellent for programming in the language. For LISP, Emacs is an IDE. Emacs itself defines a LISP dialect for its configuration and adaptation, called Emacs Lisp.
For LISP beginners that want to use Emacs, I would recommend choosing either Portacle (includes SBCL) or Lispbox (includes CCL) as ready to use options.
Both options provide an interpreter/compiler and predefined options to start Common LISP programming.
Portacle
is the most recent and up-to-date option between the two.
Portacle
The bottom panel of Portacle
provides a LISP REPL session.
Thus, you can type commands there to evaluate them.
For instance, you can test the REPL using (princ "Hello, my name is Franco!")
.
To run a file using Portacle
:
- Click on
File
, thenVisit New File...
; - Choose the path for the file.
To access the parent directory, type
..
. After choosing the path (directory, filename and extension), pressenter
. - Type the source code;
- Save the file:
File
, thenSave
; - Select the region containing the code that you want to run;
- Click on
SLIME
, accessEvaluation
, then chooseEval Region
.
The text selection with code is an interesting feature of LISP. Instead of running the whole file, you can run only part of it, depending on the selection.
Naturally, it is also possible to run the whole file (like in other programming languages).
To execute the whole file at once, you can press Ctrl c
, then Ctrl k
.
In Emacs terminology, this is written as C-c C-k
.
If you with to use usual shortcuts for text editors instead of Emacs' conventions:
- Click on
Options
; - Choose
Use CUA Keys
.
Nevertheless, you should note that CUA will change the shortcut to run the current file.
Case the shortcut changes, an alternative is typing Alt x
(in Emacs terminology, Meta x
or M-x
), then type slime-compile-and-load-file
, then press enter
.
To learn about the conventions, you can refer to the helm available at the documentation of Portacle
.
LispBox
LispBox
works similarly to Portacle
.
Like Portacle
, LispBox
uses Emacs, albeit an older version of it.
For learning, you can choose any of them.
Therefore, the most appropriate choice is usually Portacle
, as it is more up-to-date.
LispWorks
Although LispWorks requires a paid license for professional use, the Personal Edition version is free to personal use (although it is limited).
An advantage of LispWorks Personal Edition
is the ease to start programming in LISP (especially on Windows' systems).
After installing it, the program is ready to use.
As Emacs is an editor that requires efforts to learn, LispWorks Personal Edition
may be a simpler choice to start programming in LISP without further complications.
LispIDE
An alternative to LispWorks
for Windows is called LispIDE.
For the latest versions, you should access the downloads on GitHub.
If you choose LispIDE, first you will need to install an interpreter/compiler for LISP (such as SBCL for Windows).
On the first use, you will need to provide the LISP's install path.
For the 64-bit install (AMD64), the default directory is C:\Program Files\Steel Bank Common Lisp
.
To run a line of LISP code, the cursor should be after the parenthesis.
Next, choose Edit
, then Send to Lisp
(or press Shift Enter
).
Other Options
For other IDE options, there are programs supporting extensions.
First Steps to Begin Programming in LISP
The following source code snippets illustrate some resources of the LISP programming language. At this time, it is not necessary to fully understand them; the purpose is showing resources and the syntax of the language.
There are three ways of using the code. You can:
- Type (or copy and paste) the code directly into the language's interpreter;
- Write and run the code in the IDE of your choice;
- Write the code using a text editor and run the created file in the interpreter.
The examples are the same adopted for JavaScript. Therefore, you can compare languages, and notice similarities and differences between them.
Getting to Know LISP Through Experimentation
Text writing:
(princ "One line.") (terpri) (format t "Another line.") (princ "One line.\nAnother line.") (terpri)
Comments (text that is ignored by the interpreter; documentation):
(princ "Interpreter processes") ;; Interpreter ignores. (terpri)
#| <- Here the comment starts. It can spawn multiple lines. Here it ends -> -> |#
#| It can also start and end in the same line. |#
;; Though, for single line comments, it is easier to use this comment style.
It is also possible to create a comment with a single semicolon (
;
). Comments with a single one are aligned to the right.Mathematics operations:
Sum, subtraction, multiplication and division (documentation):
(princ (+ 1 1)) (terpri) (format t "~d~%" (- 2 2)) (format t "~d~%" (* 3 3)) (format t "~d~%" (/ 4 4)) ;; What does happen if you try to divide by 0? Try it!
Math expressions:
(format t "~F~%" (+ 1 (- 2 3) (* 4 (/ 5 6.0)))) (terpri)
Power (documentation):
(princ (expt 5 2)) (terpri)
Square root (documentation: sqrt()):
(princ (sqrt 25)) (terpri)
Trigonometric functions, such as sin (documentation: sin() and pi):
(princ (sin (/ pi 2.0))) ;; Sin. (terpri)
Comparisons (result in
t
meanstrue
;nil
meansfalse
):Equality (documentation; strings):
(princ (= 1 2)) ;; Equal. (terpri) (format t "~d~%" (/= 1 2)) ;; Different.
(format t "~d~%" (string= "Franco" "Franco")) (format t "~d~%" (string/= "Franco" "Franco")) (format t "~d~%" (string/= "Franco" "Seu Nome")) ;; LISP differs lower case characters from upper case ones (and vice-versa). (format t "~d~%" (string= "F" "f")) (format t "~d~%" (string/= "F" "f")) (format t "~d~%" (string= "Franco" "franco")) (format t "~d~%" (string/= "Franco" "franco"))
Other comparisons (documentation):
(format t "~d~%" (< 1 2)) ;; Less than. (format t "~d~%" (> 1 2)) ;; Greater than. (format t "~d~%" (<= 1 2)) ;; Less or equal than. (format t "~d~%" (>= 1 2)) ;; Greater or equal than.
Variables and assignment (documentation: defvar(); setq()):
Variables are like boxes that store values put inside them. The assignment operator commits the storage, which uses
setq()
in LISP. Variable declaraion usesdefvar()
.(defvar x 123) (princ x) (terpri)
(defvar result (+ 123.456 987.654)) (princ result) (terpri)
You should note that you can declare a variable with a chosen name only once. However, you can change its value as many times as you need.
(defvar name "Franco") (format t "~d~%" name) (setq name "Franco Garcia") (format t "~d~%" name)
(defvar variables_can_vary "Franco") (format t "~d~%" variables_can_vary) (setq variables_can_vary "Seu Nome") (format t "~d~%" variables_can_vary) (setq variables_can_vary "Outro Nome") (format t "~d~%" variables_can_vary)
(defvar logical_value t) (format t "~d~%" logical_value) (setq logical_value nil) (format t "~d~%" logical_value) (setq logical_value (= (+ 1 1) 2))
Constants (documentation):
(defconstant _PI 3.14159) (format t "~d~%" _PI)
(defconstant E 2.71828) (format t "~d~%" E) (setq E 0) ;; Error; the value of a constant cannot be changed once set.
Errors:
(princ Ooops!) ;; Text should be between double quotes, single quotes, or grave accents. (pri "Incorrect name for princ") (princ (/ 1 0)) (princ (/ 0 0))
Strings for words and text (documentation):
(format t "Ok, this is a valid string") (format t "Ok, this is another valid string") (format t "Ok, this is also a valid string")
(format t "If you want to 'mix' `quotes`, you have to use those different from the external ones.") (format t "Otherwise, you will need to escape them with a backslash, like this: \". The backslash is required.")
Logical operators (documentation):
(format t "~d~%" (and t t)) ;; This is a logical "and". (format t "~d~%" (or t nil)) ;; This is a logical "or". (format t "~d~%" (not t)) ;; This is a logical "not".
Conditions (documentation):
(defvar browser "Firefox") (if (string= browser "Firefox") (princ "Mozilla Firefox.")) (terpri)
(defvar my_browser "Your Browser") (if (string= my_browser "Firefox") (princ "You use a browser by Mozilla.") (princ "You use another browser.")) (terpri)
(defvar i_use "firefox") (setq i_use (string-downcase i_use)) (if (string= i_use "firefox") (princ "You use a browser by Mozilla.") (if (or (string= i_use "chrome") (string= i_use "chromium")) (princ "You use a browser by Google.") (if (string= i_use "edge") (princ "You use a browser by Microsoft.") (if (string= i_use "safari") (princ "You use a browser by Apple.") (if (string= i_use "internet explorer") (princ "You should use a more modern browser...") (princ "You use another browser.")))))) (terpri)
Loops (documentation):
(loop for i from 0 to 4 by 1 do (princ i) (terpri))
(defvar j 0) (loop while (< j 5) do (princ j) (terpri) (incf j))
(defvar k 0) (loop (princ k) (terpri) (incf k) (when (>= k 4) (return k)))
Functions (documentation):
(defun my_function (x y) (let ((result (+ x y))) result)) ;; A function is a block of code that performs arbitrary processing as defined ;; by the programmer. ;; After the definition, you can execute the function whenever wanted, using ;; a function call. (defvar z (my_function 12 -34)) ;; This is an example of a function call. (princ z) (terpri) (princ (my_function 1 2)) ;; This is another example. (terpri)
Data types (documentation):
(defvar integer_number 1) (defvar another_integer_number -1) (defvar real_number 1.23) (defvar logic_value t) ;; or nil; it can only be t or nil. (defvar string_for_text "Text here. Line breaks use\nthat is, this will be at\n the third line.")
Input (documentation: read-line(), parse-integer(), and finish-output()):
To use this example in REPL, you must type (or copy and paste) one line at a time. This is required due to the use of
read-line()
, which will ask for the input of a value. You should type a value and pressenter
to send it to the interpreter. If you define a script, this is not necessary; the file can store the entire code for the program.;; Once there is a request for a value, type one then press `enter`. (princ "What is your name? ") (finish-output) (defvar your_name (read-line)) (princ "How old are you? ") (finish-output) (defvar your_age (parse-integer (read-line))) (princ your_name) (terpri) (princ your_age) (terpri) ;; The function concatenate() performs an operatoin called concatenation ;; that combines the second string after the first. (princ (concatenate 'string' "Hello, " your_name "!")) (terpri) (format t "You are ~d years old." your_age) (terpri)
Congratulations! You Are Already Able to Write Any Program in LISP
Don't you believe it? You can find the explanation in the introduction to JavaScript
In short, it is not enough to learn the syntax of a language to solve problems using it. It is much more important learning programming logic and developing computational thinking skills than learning the syntax of a programming language. In fact, when you are in doubt about the syntax, you just have to consult the documentation. You do not have to memorize it.
After you learn a first programming language, it is relatively simple to learn other languages (that adopt similar programming paradigms to the first one). To verify this statement, you can open a new window in your browser and place it side by side with this one. Then, you can compare the source code blocks written in LISP (in this window) and in Python (in the second window).
If you wish to perform comparisons with other programming languages, the following options are available:
Next Steps
Once the development environment is configured, you can continue your system development journey.
To avoid repetitions, I recommend reading the page about configuring the JavaScript environment. Even if you are not interested at the language, many discussions are relevant to any programming language. Besides, you will understand a way to create Internet pages and will be able to create content for your browser.
Until GDScript (for Godot Engine), the topics describe develoment environment configurations for a few programming languages. After GDScript, the focus becomes basic concepts for learning programming.