Lisp Library

The Lisp Library feature allows you to extend uLisp with your own library of function or variable definitions written in Lisp. They are stored as text in flash memory along with the uLisp code, and get loaded when you run uLisp.

You can either load the entire Lisp Library when uLisp starts, or you can load individual function or variable definitions using require.

You can also list the functions and variables defined in the Lisp Library using list-library.

Note that this is separate from save-image and load-image, which use the processor's EEPROM or flash memory, or an SD card. The Lisp Library can be used even on platforms with no EEPROM or SD card, where save-image and load-image are not available. Where they are available you can still use them to save a snapshot of your workspace without affecting the Lisp Library.

For a file containing several useful functions you might like to provide in a Lisp Library see:

Adding useful functions to uLisp

Defining a Lisp Library

For example, suppose you would like your uLisp environment to include these square and cube functions:

(defun square (x) (* x x))
(defun cube (x) (* x x x))

In the uLisp source

You can define these as a Lisp Library by editing the definition of LispLibrary[] at the start of your uLisp source to:

const char LispLibrary[] PROGMEM =
"(defun square (x) (* x x))"
"(defun cube (x) (* x x x))";

Note: on the ESP8266 omit the PROGMEM.

In a separate LispLibrary.h file

Alternatively, you can keep your Lisp Library definitions separate from the uLisp source code by creating a separate LispLibrary.h file in the same Arduino project folder as the uLisp source file, and put the definition in that.

Comment out the definition of LispLibrary[] at the start of the uLisp source:

// Lisp Library
// const char LispLibrary[] PROGMEM = "";

Then add a reference to the LispLibrary.h file in the main source file by uncommenting the line:

#include "LispLibrary.h"

Direct commands

You can include a direct call to a function to run a program when the processor is reset.

For example, defining the following Lisp Library:

const char LispLibrary[] PROGMEM =
"(defun blink (x) (pinmode 13 t) (digitalwrite 13 x) (delay 1000) (blink (not x)))"
"(blink t)";

will cause the program to run and blink the LED when the processor is reset.

Loading the Lisp Library

Loading the entire Lisp Library at startup

To load all the functions and variables defined in the Lisp Library at startup uncomment the #define:

#define lisplibrary

Loading an individual function or variable definition

To load individual functions or variable definitions only when you need them, leave the #define commented:

// #define lisplibrary

and give a command such as:

(require 'square)

Listing the contents of the Lisp Library:

To list the functions and variables defined in the Lisp Library use the list-library command. For example:

> (list-library)
square cube

Creating a Lisp library

Listing programs

A convenient way to create a Lisp Library is as follows:

  • Define the functions you want to include in the Lisp Library, and test them from the Serial Monitor.
  • List the functions in the workspace with the command:
(pprintall)
  • Select the listings from the Serial Monitor window and paste them into the source window.
  • Add the line:
const char LispLibrary[] PROGMEM =
  • Add the double quotes at the start and end of each line, and a final semicolon.
  • Escape double quotes in your source, where necessary, as described in the next section.

Quoting and escapes

Due to the string conventions in C each line must start and end with a double-quote, as in the above example.

Also, any double quotes in your Lisp source must be escaped with a backslash. So for example, to include the following function in the Lisp Library:

(defun error (string) (princ "Error:") (princ string) (terpri))

you would need to enter it as:

"(defun error (string) (princ \"Error:\") (princ string) (terpri))"

Backslashes in your uLisp program need to be escaped with an extra backslash, so to include the following program:

(defun wow () (print "She said \"Wow!\""))

it will need to be:

"(defun wow () (print \"She said \\\"Wow!\\\"\"))"