LISP - 数据类型
Lisp - 数据类型
Section titled “Lisp - 数据类型”Common Lisp 中一个核心概念是:变量是无类型的(untyped),但值是有类型的(typed)。这意味着任何变量都可以存储任何类型的数据,但系统中的每份数据(或称对象)都知晓自身的类型。这使得 Lisp 兼具动态语言的灵活性和丰富而强大的类型系统。
Lisp 类型层级结构
Section titled “Lisp 类型层级结构”Lisp 中的所有对象都属于一个类型层级结构。该层级结构的根是 T,它代表所有类型的父类型(或称超类型)。层级结构的底部是 NIL,这是一个没有成员的类型。Common Lisp 提供了丰富的内置类型。
核心数据类型说明符
Section titled “核心数据类型说明符”以下是一些最基本、最常用的类型说明符:
- 数字(Numbers):
number,integer(整数),fixnum(定长整数),bignum(大整数),ratio(有理数),float(浮点数),complex(复数) - 字符(Characters):
character(字符),standard-char(标准字符) - 符号(Symbols):
symbol(符号),keyword(关键字),null(对象nil的类型) - Cons 单元格和列表(Cons Cells and Lists):
cons(构造函数),list(列表),null(空列表的类型) - 数组(Arrays):
array(数组),vector(向量),simple-vector(简单向量),string(字符串),simple-string(简单字符串),bit-vector(位向量) - 序列(Sequences):
sequence(序列,是list和vector的超类型) - 函数(Functions):
function(函数),compiled-function(编译函数) - 结构体和对象(Structures and Objects):
structure-object(结构体对象),standard-object(标准对象,来自 CLOS)
检查类型:type-of 和 typep
Section titled “检查类型:type-of 和 typep”Lisp 提供了两个用于处理类型的主要函数:
type-of object: 返回object类型的类型说明符。结果可能依赖于具体的实现,因此它最适用于交互式调试。typep object type-specifier: 这是一个谓词(predicate),如果object属于指定的类型,则返回T;否则返回nil。这是检查对象类型的推荐且可移植的方式。
示例:检查变量
Section titled “示例:检查变量”(let ((my-integer 42) (my-float 3.14) (my-string "hello") (my-list '(a b c)))
;; --- 使用 type-of(用于调试)--- (format t "Type of my-integer: ~s~%" (type-of my-integer)) ; 可能是 FIXNUM 或 (UNSIGNED-BYTE 62) (format t "Type of my-string: ~s~%" (type-of my-string)) ; 可能是 (SIMPLE-ARRAY CHARACTER (5))
;; --- 使用 typep(用于健壮的类型检查)--- (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)))输出(64位 SBCL 示例)
Section titled “输出(64位 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? T现代实践:可选的类型声明
Section titled “现代实践:可选的类型声明”尽管 Lisp 是动态类型的,但你可以提供可选的类型声明。这些声明主要有两个目的:
- 性能: 它们向编译器提供提示,通过避免泛型操作和运行时类型检查,从而生成更专业化、更快的机器代码。
- 错误检查: 现代编译器可以使用这些声明在编译时警告你是否向函数传递了错误类型的数据。
示例:一个有类型约束的函数
Section titled “示例:一个有类型约束的函数”;; 此函数用于计算圆的面积。;; 我们声明半径必须是浮点数。(defun circle-area (radius) (declare (type float radius)) (declare (optimize (speed 3) (safety 0))) ; 要求编译器优先考虑速度 (* pi radius radius))
;; 使用正确类型调用它,既能工作又速度快。(print (circle-area 10.0))
;; 使用错误类型调用它可能会发出编译时警告或运行时错误,;; 具体取决于实现和安全设置。;; (circle-area 10) ; 这可能会被标记出来。314.15927