common-lisp - SBCL 中的 "explicit-check"声明标识符是什么意思?

标签 common-lisp sbcl

在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-checkSBCL manual .

最佳答案

根据代码中的以下来源,似乎explicit-check表示与函数参数关联的类型,由 FTYPE 声明声明,不会自动检查,而是显式检查(手动)。
这避免了在某些函数 f 时进行冗余检查调度一个参数的类型 a到专门的功能 f_a其签名由 FTYPE 声明.没有 explicit-checkf_aa的类型将被检查两次,一次是在类型分派(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 的效果相同为函数声明(ftypedefknown 都设置了这个信息槽)。
    但是,这里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/

    相关文章:

    lisp - defun 以列表作为参数

    macros - 在 Lisp 宏的 lambda 列表中组合 &key 和 &rest 的最佳方式是什么?

    common-lisp - 如何使用 Quicklisp 更新依赖项?

    lisp - sbcl(和 clisp): When is a character not a character?(使用 defconstant)

    common-lisp - 具有 SBCL 外部接口(interface)的 Win32 MessageBox

    lisp - CLISP : Collecting all keywords supported

    clojure - 是否有可能通过 SBCL(或其他快速 Lisp)实现 Clojure(或 Clojure 语法)?

    common-lisp - 为什么使用 defpackage 会导致名称冲突?

    emacs - SLIME 和 SWANK 入门 : Lisp connection closed unexpectedly: connection broken by remote peer

    linux - 给BT :MAKE-THREAD a htop visible name (SBCL)