1.1 Origins

The Lisp programming language family, originating in the late 1950s, had diversified into numerous dialects by the 1980s. This fragmentation posed challenges for portability and interoperability. In response, an international effort began in the late 1980s under the auspices of the International Organization for Standardization (ISO) to define a common core Lisp. The goal was to create a minimal, portable dialect that retained the essential features of Lisp—symbolic computation, list processing, and recursion—while being simpler than Common Lisp and more practical than Scheme for certain applications. The work was carried out by ISO/IEC JTC 1/SC 22/WG 16, the Lisp working group.

1.2 ISO/IEC 13816:1997

The first edition of the ISLISP standard, ISO/IEC 13816:1997, was published in 1997. It specified a core language including a small set of data types, a procedural and functional programming model, a condition system, and an object system (ILOS). The standard aimed to balance simplicity with practical utility, providing a foundation that could be implemented efficiently on diverse hardware and operating systems. Conformance requirements were defined for both interpreters and compilers, and the standard included a comprehensive set of library functions.

1.3 Subsequent revisions and amendments

After the initial publication, minor revisions and technical corrigenda were issued to clarify ambiguities and correct errors. The standard was reaffirmed in 2007 and again in 2012, with no major changes to the language specification. Work on a more substantial revision has been discussed within the Lisp community, but as of the mid-2020s no new edition has been published. The existing standard remains stable, and implementations have continued to evolve independently.

2.1 Core data types

ISLISP provides a compact but complete set of built-in data types, divided into atomic and composite categories. All types are first-class values.

2.1.1 Atomic types: numbers, symbols, characters

Numbers in ISLISP include integers (exact) and floating-point numbers (inexact). Both follow the usual arithmetic semantics. Symbols are named data objects used primarily for identifiers and enumeration. Characters represent single characters of text, with Unicode support in later implementations. The boolean values #t and #f are symbols by convention, though the standard treats them as symbols.

2.1.2 Composite types: lists, vectors, strings

Lists are the canonical composite type in Lisp, constructed from cons cells. ISLISP supports proper lists (terminated by nil) and dotted lists. Vectors are fixed-length arrays of arbitrary elements, indexed from 0. Strings are vectors of characters with additional string-specific operations. All composite types can be nested.

2.2 Functions and macros

2.2.1 Function definition and lambda expressions

Functions are defined using the defun special form, which specifies a name, parameter list, and body. Anonymous functions are created with lambda. ISLISP uses lexical scoping by default, with closures capturing the surrounding lexical environment. Functions are first-class objects and can be passed as arguments or returned as values.

2.2.2 Macro system

The macro system allows compile-time transformation of code. Macros are defined using defmacro and work by rewriting s-expressions before evaluation. ISLISP macros are hygienic in the sense that variable capture is avoided by convention, but the language does not enforce hygiene. Macros are widely used to extend the language syntax and implement domain-specific constructs.

2.3 Object system (ILOS)

ISLISP includes an Integrated Object System (ILOS), inspired by the Common Lisp Object System (CLOS) but simplified. ILOS supports classes, generic functions, and multiple inheritance.

2.3.1 Classes and objects

Classes define data slots and behavior. Slots are accessed via accessor functions. Objects are instances of classes, created with make-instance. Classes are themselves objects (first-class). The class hierarchy includes a root class t and a built-in class class.

2.3.2 Generic functions and methods

Generic functions are functions whose behavior depends on the types of their arguments. Methods are defined separately from classes, using defmethod. Method dispatch is based on the classes of all required arguments (multiple dispatch). Methods can be specialized on a subset of arguments, and the most specific applicable method is called.

2.3.3 Multiple inheritance

A class can inherit from more than one direct superclass. The method combination and slot inheritance follow a linearization algorithm (C3 linearization in some implementations, though the standard does not mandate a particular algorithm). Conflicts between inherited slots or methods are resolved by precedence ordering.

2.4 Error handling and conditions

ISLISP provides a condition system for handling exceptional situations. This system is modeled after the Common Lisp condition system but is more minimal.

2.4.1 Condition system

Conditions are objects representing an exceptional situation. When a condition is signaled (via signal), the system searches for an active handler. If no handler is found, the system may invoke a restarts or fall back to default behavior (e.g., entering a debugger). Conditions are organized in a hierarchy of types, allowing fine-grained handling.

2.4.2 Restarts and handlers

Handlers are functions established with handler-bind or handler-case that are invoked when a matching condition is signaled. Restarts are points to which the program can transfer control after a condition is handled. They are defined with with-restarts and invoked by the handler via invoke-restart. This separation allows the handler to choose how to recover (e.g., retry, use a default value, abort) without coupling it to the location of the error.

3.1 Basic syntax

3.1.1 S-expressions

ISLISP code is written as s-expressions (symbolic expressions), which are either atoms (numbers, symbols, characters, strings) or lists. Lists represent function calls, macro invocations, or special forms. The reader parses s-expressions into internal data structures.

3.1.2 Reader macros

The reader supports reader macros—functions that customize how the input stream is parsed. The standard defines a set of built-in reader macros (e.g., ' for quoting, ` ` , , , @` for quasi-quoting). Implementations may allow user-defined reader macros, though the standard does not require it.

3.2 Special forms

Special forms are syntactic constructs that are not function calls. They control evaluation order, variable binding, and more.

3.2.1 Control flow: if, cond, case, loop

if evaluates a test and then one of two branches. cond performs multi-way conditional branching. case tests a value against a set of literal keys. loop is a simple iterative construct (not the full loop macro of Common Lisp, but a basic form). Recursion is the primary iteration mechanism.

3.2.2 Variable binding: let, let*, setq

let and let* introduce local bindings; let* allows sequential binding. setq assigns to existing variables. ISLISP uses lexical scoping for let bindings. Dynamic variables are possible via special declarations.

3.2.3 Function application and lexical scope

Function application is denoted by a list whose first element is the function. The arguments are evaluated in applicative order (all arguments evaluated before the function call). Lexical scope means that the meaning of a variable is determined by its enclosing lexical context, not the call stack. ISLISP uses lexical scope by default, except for variables declared special.

3.3 Evaluation model

3.3.1 Normal order vs. applicative order

ISLISP uses applicative-order evaluation: in a function call, all arguments are evaluated before the function is applied. Normal-order evaluation (lazy evaluation) is not built-in but can be simulated with macros and closures.

3.3.2 Dynamic vs. lexical scoping

Lexical scoping is the default. Dynamic scoping, in which variable references are resolved in the call stack, is available for variables declared special. This is used mainly for global parameters and for certain constructs like the condition system that rely on dynamic bindings.

4.1 Open source implementations

4.1.1 OpenLisp

OpenLisp is one of the primary open-source implementations of ISLISP, originally developed by Christian Jullien. It is written in C and ISLISP itself, and aims for portability and compliance with the ISO standard.

4.1.1.1 Development history and maintenance

OpenLisp began in the mid-1990s as a minimal ISLISP interpreter. Over time it added a compiler, an embeddable runtime, and support for foreign function interfaces. Maintenance has been sporadic but consistent; the latest stable release as of 2024 is version 10.0. OpenLisp is often used as a reference implementation for the standard and is available for multiple operating systems.

4.1.2 Other open source ISLISP systems

Several other open-source implementations, often experimental, exist. These include Ilisp (a small interpreter), ISLisper (a Scheme-based implementation), and various student projects. Few are fully compliant with the standard; most implement a substantial subset.

4.2 Commercial implementations

Commercial implementations of ISLISP are rare. Some companies have developed internal ISLISP systems for embedded or legacy use. One notable commercial product is the LispWorks ISLISP module (now discontinued), which provided ISLISP within the LispWorks environment. The market for commercial ISLISP implementations remains small.

5.1 Educational use

5.1.1 Teaching Lisp fundamentals

ISLISP’s minimal core makes it suitable for introductory programming courses that focus on Lisp concepts. Students can learn recursion, symbolic manipulation, and functional programming without the complexity of larger dialects. Its small number of special forms reduces the initial learning curve.

5.1.2 Curriculum integration

Some universities have used ISLISP as a teaching language in courses on programming languages, artificial intelligence, or symbolic computation. It can be paired with a simple IDE or embedded in educational platforms. The existence of the ISO standard provides a stable reference for course materials.

5.2 Industrial and research use

5.2.1 Domain-specific applications

ISLISP has been used in research projects requiring a portable Lisp, such as expert systems, natural language processing, and prototyping. Its small footprint makes it suitable for embedded systems or resource-constrained environments. However, industrial adoption is limited compared to Common Lisp or Scheme.

5.2.2 Embedding and scripting

The lightweight nature of ISLISP implementations allows embedding in larger applications as a scripting language. For example, OpenLisp has been embedded in network routers and industrial controllers. Its syntax and semantics are Lisp-like, appealing to developers familiar with the family.

6.1 Common Lisp

Common Lisp is a much larger and more feature-rich language than ISLISP. While ISLISP shares many core concepts (e.g., cons cells, functions, macros, an object system), it omits many Common Lisp features such as multiple values, readtables, the full loop macro, and extensive numeric towers. ISLISP is intended to be a minimal subset that is easier to implement and learn.

6.2 Scheme

Scheme is another minimalist Lisp dialect, but with a focus on functional programming, lexical scoping, and continuations. ISLISP includes an object system and a condition system, which Scheme lacks in its standard form. Scheme uses a different library and module system, and its macro system (syntax-rules) differs from ISLISP’s defmacro. Both are standardized, but ISLISP’s standard is from ISO; Scheme is standardized by the IEEE and R6RS/R7RS committees.

6.3 Emacs Lisp

Emacs Lisp (Elisp) is the scripting language of the Emacs editor. It is dynamically scoped and lacks a formal standard. ISLISP’s lexical scoping and modern object system are significant differences. Elisp is tailored to text editing, while ISLISP is a general-purpose language.

6.4 Other standardized Lisp dialects

Historically, there have been other attempts at Lisp standardization, such as the IEEE Scheme standard (IEEE 1178-1990) and the ANSI Common Lisp standard (X3.226-1994). ISLISP remains the only ISO standard for Lisp. Its niche is that of a “common denominator” Lisp that can be both a teaching language and a portable implementation target.