LISP - 向量函数
Lisp - 向量函数
Section titled “Lisp - 向量函数”向量(Vector)是 Common Lisp 中一种基本的序列(sequence)类型,提供 O(1) 的随机访问(random access)元素能力。本章将探讨创建、修改和操作向量的关键函数,遵循现代和地道的实践。
修改向量元素
Section titled “修改向量元素”向量的单个元素使用 (setf aref) 进行修改。
使用 (setf aref)
Section titled “使用 (setf aref)”aref (ARray REFerence) 是用于访问任何数组(array),包括向量元素的通用函数。svref 是针对简单向量(simple vectors)的专用版本,速度可能更快,但 aref 更通用,通常就足够了。
(let ((my-vector (vector 10 20 30 40))) (format t "Original vector: ~a~%" my-vector)
;; 修改索引为 2 的元素(第三个元素) (setf (aref my-vector 2) 99)
(format t "Modified vector: ~a~%" my-vector))Original vector: #(10 20 30 40)Modified vector: #(10 20 99 40)使用 fill
Section titled “使用 fill”The fill 函数能高效地将向量的所有元素或子序列设置为单个值。
(let ((my-vector (vector 1 2 3 4 5))) (format t "Original vector: ~a~%" my-vector)
;; 将整个向量填充为 0 (fill my-vector 0)
(format t "Filled vector: ~a~%" my-vector))Original vector: #(1 2 3 4 5)Filled vector: #(0 0 0 0 0)访问向量信息
Section titled “访问向量信息”你可以检查向量的属性,例如其长度和元素类型。
;; 通用向量可以容纳任意类型的元素 (T)(let ((general-vector (vector "hello" 42 #\c))) (format t "Vector: ~a~%" general-vector) (format t " Length: ~a~%" (length general-vector)) (format t " Element Type: ~a~%" (array-element-type general-vector)))
(terpri)
;; 专用向量针对特定类型(如整数)进行了优化(let ((specialized-vector (make-array 3 :element-type 'fixnum :initial-contents '(100 200 300)))) (format t "Vector: ~a~%" specialized-vector) (format t " Length: ~a~%" (length specialized-vector)) (format t " Element Type: ~a~%" (array-element-type specialized-vector)))Vector: #("hello" 42 #\c) Length: 3 Element Type: T
Vector: #(100 200 300) Length: 3 Element Type: FIXNUM函数式向量操作
Section titled “函数式向量操作”Common Lisp 的函数式(functional)传统通过 map 和 reduce 等高阶函数(higher-order functions)得以体现,它们可以在向量上操作以生成新结果,而不会产生变异(mutation)。
使用 map 进行转换
Section titled “使用 map 进行转换”map 函数将一个函数应用于序列的每个元素,返回一个新的序列。第一个参数 'vector 指定结果应为向量。
(let* ((original (vector 1 2 3 4 5)) (doubled (map 'vector #'(lambda (x) (* x 2)) original)))
(format t "Original: ~a~%" original) (format t "Doubled: ~a~%" doubled))Original: #(1 2 3 4 5)Doubled: #(2 4 6 8 10)使用 reduce 进行聚合
Section titled “使用 reduce 进行聚合”reduce 函数使用一个二元函数(binary function)将序列的元素组合成单个值。
(let* ((numbers (vector 1 2 3 4 5 6)) (sum (reduce #'+ numbers)))
(format t "Numbers: ~a~%" numbers) (format t "Sum: ~a~%" sum))Numbers: #(1 2 3 4 5 6)Sum: 21最佳实践:测试你的函数
Section titled “最佳实践:测试你的函数”在编写操作向量的函数时,对其进行测试至关重要。虽然对于项目而言,推荐使用像 FiveAM 或 Prove 这样的完整测试框架(testing frameworks),但你可以使用 assert 进行简单的检查。
(defun sum-vector (vec) (reduce #'+ vec))
;; 测试用例(assert (= (sum-vector (vector 1 2 3)) 6))(assert (= (sum-vector (vector)) 0))(assert (= (sum-vector (vector -1 1)) 0))
(format t "All sum-vector tests passed!~%")这种简单方法可以验证你的函数对典型输入、空输入(一种边缘情况,edge case)以及其他场景是否有效。