Common Lisp

from Wikipedia, the free encyclopedia
Common Lisp
logo

Unofficial Lisp logo
Basic data
Paradigms : multiparadigmatic: functional , procedural , modular , object-oriented , reflexive
Publishing year: 1984, 1994 for ANSI Common Lisp
Designer: Scott E. Fahlman , Richard P. Gabriel , David Moon
Developer: ANSI X3J13 committee
Typing : dynamic
Important implementations : Allegro Common Lisp , Armed Bear Common Lisp , CLISP , Clozure CL, CMUCL , Embeddable Common Lisp , GNU Common Lisp , LispWorks , Movitz , Poplog , Scieneer Common Lisp , Steel Bank Common Lisp
Dialects: CLtL1, CLtL2, ANSI Common Lisp
Influenced by: Lisp Machine Lisp, Maclisp , Symbolics ZetaLisp , Scheme , Interlisp
Affected: Dylan , Eulisp , ISLisp , Ruby , SubL
common-lisp.net

Common Lisp (often abbreviated as CL ) is a multi paradigms - programming language within the language family Lisp . It emerged from an effort started in 1981 under the direction of Scott Fahlman to find a standardized dialect as the successor to Maclisp (and its variants) and was standardized in 1994 as ANSI Common Lisp .

history

In 1984 the first edition of the book Common Lisp: The Language ( CLTL1 for short ) appeared, which contained the first specification of the language. Shortly afterwards, the ANSI sub-committee X3J13 was founded to create a standard based on the specification. The second edition of the book ( CLTL2 ) from 1990 contained changes by the sub-committee and describes an interim status . The final version of the standard appeared in 1994 ( ANSI / X3.226-1994 ).

syntax

Common Lisp uses S expressions to represent both source code and data. Function and macro calls are written as lists that contain the name of the function or macro as the first element. Comments are introduced with ;or #| |#enclosed.

;; Addiere 2 und 2
(+ 2 2)

;; Definiere die Variable *p* als 3,1415
(defparameter *p* 3.1415)

;; Setze die vorher definierte Variable *p* auf 42
(setq *p* 42)

;; Eine Funktion, die ihr Argument quadriert
(defun square (x)
  (* x x))

;; Quadriere 3
(square 3)

Data types

Common Lisp supports a wide variety of data types, more than many other languages. These types are arranged hierarchically.

Scalar types

Numbers in Common Lisp are of type number . Subtypes of number include integer (whole numbers ), ratio (rational numbers or fractions), real ( floating point numbers ) and complex (complex numbers). Arithmetic with integers and fractions is arbitrarily precise. A class of program errors in languages ​​like C, which are caused by overflowing integers, is thus practically eliminated in Common Lisp.

The Common Lisp character type is not limited to ASCII , which is not surprising since Lisp is older than ASCII. Many implementations support Unicode .

The symbol type is a special feature of almost all Lisp dialects, but is largely unknown in other language families. A symbol in Common Lisp is similar to an identifier in other languages ​​in that it is used as a variable and can be assigned values. But since they are first class objects, they can also be used for other purposes.

Data structures

Common Lisp knows a number of predefined data structures. These include hash tables, data networks (so-called structures ), classes, streams, path names, multi-dimensional arrays and sequences. The latter include classic Lisp lists, but also bit vectors, general vectors and character strings.

  • Hashtables store assignments of objects. For example, a number can be assigned to a character string or a function to a symbol.
  • In data networks , it is arbitrarily nested structures, the data can hold any type. A single network stores values in a fixed amount of so-called slots that can later be changed and extracted at will. Structures form a simple inheritance hierarchy.
  • Arrays are n-dimensional lists of values ​​that either all have to be of the same type (in so-called homogeneous arrays ) or - in the case of heterogeneous arrays - can be combined in any way. They support the usual matrix arithmetic operations and can also occur in dynamically changeable sizes. Compilers can usually translate calculations with homogeneous arrays of fixed size very efficiently.
  • Vectors are the special case of arrays with only one dimension. There are predefined vector types such as the character string, a vector of characters, or the bit vector, a convenient and efficient way of storing bits and calculating with them.

Classic Lisp lists consist of so-called CONS cells. This means ordered pairs whose first element, the so-called CAR, contains a value, while the second element, the so-called CDR, points to the next cell or, if the list ends, to the symbol NIL. Basically, Lisp lists are simply linked lists. Today they are mainly used to represent code and manipulate it at will with the help of macros - a mechanism that gives Common Lisp programmers a degree of freedom that is reserved for the language designer in other programming languages . More complex data is usually stored in classes or groups, and data that you want to calculate efficiently with in arrays or vectors.

Package system

Common Lisp contains a package system that allows you to define namespaces for symbols and to import and export the latter. In addition, abbreviations or nicknames can be assigned to packages for the sake of convenience and readability.

Symbols that are in namespaces other than the current one can be addressed by writing the respective package name in front of their names, separated by a colon. For example, the name cl: format always points to the FORMAT symbol in the CL package, regardless of whether a function that is also called FORMAT is possibly defined in the current package.

Functions

In Common Lisp, functions are normal objects that can be passed as parameters or returned by a function. This allows very general operations to be expressed.

The evaluation scheme for functions is very simple. Given an expression of the form , it can be assumed that the symbol named F: (F A1 A2 )

  1. is a special operator.
  2. is an already defined macro.
  3. is the name of a function.

If F is the name of a function, then the arguments A1, A2, ... are evaluated from left to right and transferred to the corresponding function as parameters.

Define new functions

The macro defundefines functions. A function definition describes the name of the function, the names of all arguments and the function body:

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

Function declarations can contain declarations that give the compiler hints for optimization and the like. a. regarding types. In addition, so-called documentation strings or docstrings for short can also be specified, which the runtime system can use to offer the user interactive help.

 (defun square (x)
   "Berechne das Quadrat von X."
   (declare (fixnum x)    ; Typangabe für ein Argument
            (optimize (speed 3)
                      (debug 0)
                      (safety 1)))
   (the fixnum (* x x)))  ; Typangabe für den Rückgabewert

Anonymous functions (functions without explicit names) are generated using the lambdaoperator (according to the lambda calculus ). Many Common Lisp programs use higher order functions where it is useful to pass anonymous functions as arguments.

Read, compile, and runtime

As a special feature compared to other languages, Common Lisp allows the programmer to not only execute their own code at runtime, but also in three other phases, the read, compile and load times.

Reading time and reading macros

Code that is executed during reading time can control the parser and thus define its own syntax. Most often this is in the form of so-called reading macros ( read macros or reader macros ), the individual characters are assigned and can convert any text into code. For example, there are reading macros that provide the familiar infix syntax for arithmetic expressions and make expressions valid as in Common Lisp. 3 * (4 + 3)

A programmer can also execute code ad hoc at reading time by using the standard reading macro #.. The printout, for example, not only returns 30 when it is executed, but also prints the number 10 on the screen while the printout itself is being read. Since this functionality already makes the mere reading in of expressions, for example received via a network, a security problem, it can be switched on and off via the variable . (+ #.(print 10) 20)*read-eval*

Compile time and Lisp macros

Like almost all Lisp dialects and in contrast to most other languages, Common Lisp offers the possibility of executing code at compile time and thus manipulating, generating and transforming the S expressions representing the program code as desired. The language primarily provides the so-called macros for this. Since Lisp macros work on the level of the program structure and thus fit perfectly into the language itself, they cannot be compared with macro systems in other languages ​​and should therefore actually deserve their own name.

Macros can access all Common Lisp functionalities, including self-defined ones, which gives them a wide range of options for converting code. Common Lisp programmers often use macros to build application-specific languages ​​into Common Lisp that fit in seamlessly with the language and increase its expressiveness. It is also possible to use macros to provide new programming paradigms.

For example, the class-based object system CLOS contained in the ANSI standard can be implemented in a metacircular manner as a set of generic functions and classes, over which a layer of macros is superimposed to enable the convenient definition of classes, generic functions and other CLOS language elements. How the implementation of CLOS actually looks, however, depends on the Lisp system used and is not prescribed by the standard.

Variable binding

Like most other languages, Common Lisp has the concept of tying values ​​to names. However, it extends this concept by two aspects: on the one hand, variable names can be used as normal objects and, for example, passed on or saved, and on the other hand, two very different forms of variable binding are available. The first aspect was already explained in the section on data types.

Lexical binding and lexical variables

Common Lisp defaults lexical scoping ( lexical scoping ), a concept that Scheme in his time introduced into the Lisp world. Names are always valid in a specific, self-contained part of the source text, so that the binding cannot overlap with previously or future defined bindings.

Since links in Common Lisp can be created at any time and overlaps are excluded, it is possible to use them to create data structures simply by declaring functions. In doing so, one takes advantage of an effect known as closure : the automatic capture of ties. Closures are functions and their relationships.

For example, if you want to define the my-consoperator that generates a pair of two values, you might get the idea of ​​having it lambdareturn an anonymous function ( i.e. an expression) that has captured the two values ​​and, on request, . H. if it is called with an argument num, it returns one of the two (namely the first value for num = 0 and otherwise the second):

 (defun my-cons (x y)
   (lambda (num)
     (if (zerop num)
         x
         y)))

You can use the values ​​generated by this operator, for example, as follows (note: funcallis the operator for calling functions stored in variables):

 (defvar *paar-A* (my-cons 100      200))  ;=> *paar-A*
 (defvar *paar-B* (my-cons *paar-A* 42))   ;=> *paar-B*
 (print (funcall *paar-A* 0))              ;=> 100
 (print (funcall *paar-A* 1))              ;=> 200
 (print (funcall *paar-B* 0))              ;=> (LAMBDA ...)
 (print (funcall (funcall *paar-B* 0) 1))  ;=> 200

Please note that the various bindings of *paar-A*and *paar-B*for the names X and Y do not overlap, but my-consare created anew for each call of . It is also possible to change such bindings afterwards, as the following code snippet shows, which zählerdefines a hidden binding called :

 (let ((zähler 0))
   (defun zähler+     () (incf zähler))
   (defun zähler-     () (decf zähler))
   (defun hole-zähler () zähler))

 (hole-zähler)  ;=> 0
 (zähler+)      ;=> 1
 (zähler+)      ;=> 2
 (hole-zähler)  ;=> 2
 (zähler-)      ;=> 1
 (hole-zähler)  ;=> 1

 (setf zähler 100)  ;=> Fehler, weil zähler nicht global definiert ist.

Dynamic binding and special variables

Common Lisp still supports dynamic binding used in earlier Lisp dialects, which used global names but time-limited value bindings. Because of the potential name conflicts this kind of value binding is used only in special cases, which is why in this context of special variable , so special variable is spoken.

It is common practice to put the names of special variables between two asterisks to make their nature clear to the reader at a glance and to avoid conflict with lexical variables.

The benefit of special variables lies precisely in their temporary but global effects. They can also be thought of as a form of implicit arguments that are passed down the entire call tree without having to be explicitly named at every level.

An example makes the principle easier to understand. Let us assume that a function is print-datepredefined (for example in a third-party library) that writes the current date in a particularly beautiful form on the standard output. Now we would like to use this irreplaceable function, but instead write the result to a file. If the developer of the function has not thought of this possibility and has incorporated a corresponding parameter, we can make use of the fact that the standard output is defined as a special variable:

 (let ((*standard-output* ausgabedatei))
   (format t "~&Das aktuelle Datum ist: ")
   (print-date))

The fact that we *standard-output*dynamically ausgabedateibind to ours ensures that every standard edition ends up where we want it. letensures that the binding is reset to its initial state after the block has ended.

Special variables have another interesting aspect that comes to light in the case of concurrency (language extension to ANSI Common Lisp) and makes it impossible or at least very difficult to implement them above the actual language level: Their connections are thread-local. This means that two parallel program sequences which access the same name can use different bindings for this name, although names of special variables are global. The above code would therefore also work if another thread had the idea of *standard-output*binding to its own file between the second and third lines . Since the two bindings are independent of each other, the two threads do not interfere with each other. One speaks here of binding superimposition, because the existing binding is not changed, but new bindings are always superimposed on the old ones and letremoved again when the block is terminated .

Comparison with other Lisp dialects

Common Lisp is mainly based on the Maclisp dialect developed at MIT , but was also heavily influenced by Symbolics ZetaLisp , InterLisp and Scheme . Guy Steele , the chairman of the Common Lisp Committee, co- designed Jay Sussman with Gerald Jay in the 1970s .

In contrast to most of the other Lisp dialects, which traditionally only used dynamic variable binding, Common Lisp mainly uses the lexical variable binding (lexical scope) introduced in Scheme . See section Variable Binding .

Availability of packages and libraries

Similar to other programming languages ​​( e.g. CPAN in the case of Perl ), ASDF-Install is a collection of Common Lisp modules that can be installed automatically.

There are numerous packages for the most diverse areas of application, for example for web development, 3D graphics, word processing and much more. Bindings for GUI toolkits such as GTK + , Cocoa , Microsoft Windows , Tk and others are also available, as are implementations of the Common Lisp Interface Manager ( CLIM for short ) and a binding for .NET .

Development environments

Languages ​​with S-expression-based syntax such as Common Lisp are particularly suitable for the use of powerful code analysis and management programs thanks to their syntactic simplicity. In addition, development environments can be integrated with them in a variety of ways, including mixing up program and IDE code if necessary.

A widely used free development environment is SLIME , the Superior Lisp Interaction Mode for Emacs , which supports the usual interactive software development process in Common Lisp well. The lack of refactoring tools is seen as a major problem by only a few lispers, especially since the language itself with its macros offers good possibilities for this at the source code level.

Furthermore, many commercial Common Lisp development systems, such as exist Allegro Common Lisp by Franz Inc. and LispWorks of LispWorks Ltd .

literature

German-language books

  • RA Brooks: Programming in Common Lisp , Oldenbourg Wissenschaftsverlag, 1987, ISBN 3-486-20269-3
  • Herbert Stoyan: Programming Methods of Artificial Intelligence, Volume 1 , Springer, 1988, ISBN 978-3-540-19418-7
  • Rüdiger Esser, Elisabeth Feldmar: LISP, case studies with applications in artificial intelligence , Vieweg, 1989, ISBN 3-528-04585-X
  • Herbert Stoyan: Programming Methods of Artificial Intelligence, Volume 2 , Springer, 1991, ISBN 978-3-540-52469-4
  • Otto Mayer: Programming in Common Lisp , Spektrum Akademischer Verlag, 1995, ISBN 3-86025-710-2
  • Paul Graham: ANSI Common Lisp . Markt + Technik Verlag, 1997, ISBN 3-827-29543-2
  • Conrad Barski: Land of Lisp: Learn Lisp programming easily and program original games , mitp, 2011, ISBN 978-3-8266-9163-8
  • Patrick M. Krusenotto: Functional programming and metaprogramming, interactive in Common Lisp , Springer Fachmedien Wiesbaden 2016, ISBN 978-3-658-13743-4

Web links

Individual evidence

  1. Richard P. Gabriel mentions Scott Fahlman as the leader of the Common Lisp Project
  2. ^ A b Guy L. Steele Jr .: Common Lisp: The Language . Prentice Hall, ISBN 0-13-152414-3 .
  3. History in Common Lisp HyperSpec, accessed on November 6, 2016
  4. ^ Paul Graham : On Lisp . Prentice Hall, 1993, ISBN 0-13-030552-9
  5. see cliki.net/Unicode Support (English)
  6. cliki.net/asdf
  7. common-lisp.net