LISP - Data Types
Lisp - Data Types
Section titled “Lisp - Data Types”A fundamental concept in Common Lisp is that variables are untyped, but values are typed. This means any variable can hold any type of data, but every piece of data (or object) in the system knows its own type. This provides the flexibility of a dynamic language with a rich, powerful type system.
The Lisp Type Hierarchy
Section titled “The Lisp Type Hierarchy”All objects in Lisp belong to a hierarchy of types. The root of this hierarchy is T, which represents the supertype of all types. At the bottom is NIL, which is the type that has no members. Common Lisp provides a rich set of built-in types.
Core Data Type Specifiers
Section titled “Core Data Type Specifiers”Here are some of the most essential, commonly used type specifiers:
- Numbers:
number,integer,fixnum,bignum,ratio,float,complex - Characters:
character,standard-char - Symbols:
symbol,keyword,null(the type of the objectnil) - Cons Cells and Lists:
cons,list,null(also the type of the empty list) - Arrays:
array,vector,simple-vector,string,simple-string,bit-vector - Sequences:
sequence(a supertype oflistandvector) - Functions:
function,compiled-function - Structures and Objects:
structure-object,standard-object(from CLOS)
Inspecting Types: type-of and typep
Section titled “Inspecting Types: type-of and typep”Lisp provides two primary functions for working with types:
type-of object: Returns a type specifier for the type of theobject. The result can be implementation-dependent, so it’s best used for interactive debugging.typep object type-specifier: This is a predicate that returnsTif theobjectis of the specified type, andnilotherwise. This is the preferred, portable way to check an object’s type.
Example: Inspecting Variables
Section titled “Example: Inspecting Variables”(let ((my-integer 42) (my-float 3.14) (my-string "hello") (my-list '(a b c)))
;; --- Using type-of (for debugging) --- (format t "Type of my-integer: ~s~%" (type-of my-integer)) ; Might be FIXNUM or (UNSIGNED-BYTE 62) (format t "Type of my-string: ~s~%" (type-of my-string)) ; Might be (SIMPLE-ARRAY CHARACTER (5))
;; --- Using typep (for robust type checking) --- (format t "Is my-integer an INTEGER? ~a~%" (typep my-integer 'integer)) (format t "Is my-float a NUMBER? ~a~%" (typep my-float 'number)) (format t "Is my-string a LIST? ~a~%" (typep my-string 'list)) (format t "Is my-list a SEQUENCE? ~a~%" (typep my-list 'sequence)))Output (example from a 64-bit SBCL)
Section titled “Output (example from a 64-bit SBCL)”Type of my-integer: (UNSIGNED-BYTE 62)Type of my-string: (SIMPLE-ARRAY CHARACTER (5))Is my-integer an INTEGER? TIs my-float a NUMBER? TIs my-string a LIST? NILIs my-list a SEQUENCE? TModern Practice: Optional Type Declarations
Section titled “Modern Practice: Optional Type Declarations”While Lisp is dynamically typed, you can provide optional type declarations. These declarations serve two main purposes:
- Performance: They give hints to the compiler, allowing it to generate more specialized and faster machine code by avoiding generic operations and runtime type checks.
- Error Checking: A modern compiler can use these declarations to warn you at compile time if you are passing the wrong type of data to a function.
Example: A Typed Function
Section titled “Example: A Typed Function”;; This function calculates the area of a circle.;; We declare that the radius must be a floating-point number.(defun circle-area (radius) (declare (type float radius)) (declare (optimize (speed 3) (safety 0))) ; Ask compiler to prioritize speed (* pi radius radius))
;; Calling it with the correct type works and is fast.(print (circle-area 10.0))
;; Calling it with the wrong type might signal a compile-time warning or a runtime error,;; depending on the implementation and safety settings.;; (circle-area 10) ; This could be flagged.Output
Section titled “Output”314.15927