在SBCL的y-or-n-p源代码中,我看到了(declare (explicit-check))
(defun y-or-n-p (&optional format-string &rest arguments)
"..."
(declare (explicit-check))
(flet ((print-query ()
(apply #'maybe-print-query "(y or n)" format-string arguments)))
(loop (print-query)
(case (query-read-char)
((#\y #\Y) (return t))
((#\n #\N) (return nil))
(t (clarify-legal-query-input "y" "n"))))))explicit-check是做什么的?它在HyperSpec中没有作为标准声明标识符列出,所以它可能是实现定义的。但是,我没有看到explicit-check在SBCL手册中有任何提及。
发布于 2021-09-21 15:40:02
根据代码中的以下源代码,explicit-check似乎表明与函数参数关联的类型(如FTYPE声明所声明的)不会自动检查,而是显式地(手动)检查。
这避免了当某些函数f将一个参数a的类型分派给由FTYPE声明签名的专用函数f_a时,会进行冗余检查。如果没有explicit-check,f_a中的a类型将被检查两次,一次是在类型分派期间,一次是在输入函数时。
src/compiler/ir1-translators.lisp
检查新的全局函数定义是否与;以前的声明或定义相一致,并断言参数/结果;类型(如果适当的话)。此断言由;显式- check属性抑制,该属性针对函数指定;检查它们的参数类型,这是类型分派的结果。这避免了冗余检查,例如args上的NUMBERP到+等;FIXME:这似乎与添加"new“;;定义完全无关,因为它只从IR1--转换-内联-扩展中调用。src/compiler/ctype.lisp
(警告“没有已知FTYPE的显式检查是无意义的”)package-data-list.lisp-expr
通知编译器它不需要断言类型。“显式检查”src/compiler/ir1tran.lisp
显式检查本身指定由函数体检查所有参数和;;结果类型。在y-or-n-p上下文中,目的是只检查类型一次。这可以提前完成,例如在y-or-n-p开始时,它会调用“不安全”函数,而这些函数不检查它们的类型,但是这里不是这样的。
相反,函数是用defknown定义的,它执行以下代码:
(setf (info :function :type name) type-to-store)(见src/compiler/knownfun.lisp)
如果我没有弄错的话,这也是相同的效果,因为为函数声明了一个FTYPE ( ftype和defknown都设置了这个信息槽)。
但是,这里y-or-n-p不需要检查类型本身,因为它主要委托给另一个函数,即maybe-print-query。该函数调用format,它也被声明为explicit-check。
它所做的第一件事是对目标参数进行etypecheck,以便将对格式化的调用分派给不同的%format调用,这些调用也会根据下一个参数的类型(一个控制字符串或格式化程序函数)分支到不同的结果。
因此,在实践中,检查参数的类型与分派交织在一起,因为有很多角的情况需要考虑。
一种自顶向下的方法,即首先检查输入类型,然后传递给不安全的函数,也需要执行一些复杂的类型检查步骤,然后仍然需要根据参数类型进行分派。这可能就是为什么类型检查被推迟到代码到达不同的特殊情况。
https://stackoverflow.com/questions/69270663
复制相似问题