如何在Common Lisp/SBCL中指定&rest参数的类型?
解决方案
方法一:显式检查每个参数(兼容性最好)
在函数内部使用check-type宏逐个验证&rest参数中的元素类型,这种方式在所有Common Lisp实现中都有效,且错误提示清晰符合需求:
(deftype fruit () '(member :apple :orange :pear)) (defun place-order (&rest selections) (dolist (s selections) (check-type s fruit) ; 显式检查每个元素的类型 (format t "Ordering ~S~%" s))) (place-order :orange :apple :bacon)
调用后会触发如下错误:
Unhandled TYPE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING {1001DD0003}>: The value :BACON is not of type (MEMBER :APPLE :ORANGE :PEAR) when checking the type of S.
方法二:利用SBCL的类型扩展实现编译/运行时检查
SBCL支持proper-list扩展类型,可用来表示所有元素均为指定类型的真列表。结合高安全级别的优化声明,能让编译器在编译期(针对常量参数)或运行期(针对变量参数)进行类型检查:
(deftype fruit () '(member :apple :orange :pear)) ; 开启最高安全级别,确保类型检查生效 (declaim (optimize (safety 3))) ; 声明&rest参数为所有元素都是fruit的真列表 (declaim (ftype (function (&rest (proper-list fruit))) place-order)) (defun place-order (&rest selections) (dolist (s selections) (format t "Ordering ~S~%" s))) (place-order :orange :apple :bacon)
如果调用时传入的是常量参数,SBCL会在编译阶段直接报错;如果是变量参数,则会在运行时触发类型错误。
内容的提问来源于stack exchange,提问作者Dan Passaro
相关产品推荐
相关产品推荐

