在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 manual .
最佳答案
根据代码中的以下来源,似乎explicit-check
表示与函数参数关联的类型,由 FTYPE
声明声明,不会自动检查,而是显式检查(手动)。
这避免了在某些函数 f
时进行冗余检查调度一个参数的类型 a
到专门的功能 f_a
其签名由 FTYPE
声明.没有 explicit-check
在 f_a
,a
的类型将被检查两次,一次是在类型分派(dispatch)期间,一次是在进入函数时。
src/compiler/ir1-translators.lisp
;;; Check a new global function definition for consistency with
;;; previous declaration or definition, and assert argument/result
;;; types if appropriate. This assertion is suppressed by the
;;; EXPLICIT-CHECK attribute, which is specified on functions that
;;; check their argument types as a consequence of type dispatching.
;;; This avoids redundant checks such as NUMBERP on the args to +, etc.
;;; FIXME: this seems to have nothing at all to do with adding "new"
;;; definitions, as it is only called from IR1-CONVERT-INLINE-EXPANSION.
src/compiler/ctype.lisp
(warn "Explicit-check without known FTYPE is meaningless")
package-data-list.lisp-expr
;; Advice to the compiler that it doesn't need to assert types.
"EXPLICIT-CHECK"
src/compiler/ir1tran.lisp
;; EXPLICIT-CHECK by itself specifies that all argument and
;; result types are checked by the function body.
在
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
不需要检查类型本身,因为它主要委托(delegate)给另一个函数,即 maybe-print-query
.该函数调用 format
,也声明为 explicit-check
.它做的第一件事就是
etypecheck
目标参数,以便将格式调用分派(dispatch)到 %format
的不同调用,这反过来也根据下一个参数的类型(控制字符串或格式化程序函数)分支出不同的结果。所以在实践中,检查参数的类型与调度是交错的,因为有很多极端情况需要考虑。
首先检查输入类型然后传递给不安全函数的自顶向下方法也需要执行一些复杂的类型检查步骤,然后仍然需要根据参数类型进行调度。这可能就是为什么类型检查会延迟到代码到达不同的特殊情况。
关于common-lisp - SBCL 中的 "explicit-check"声明标识符是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69270663/