types - 常见口臭类型的综合指南

标签 types common-lisp slots clos

也许这个问题太笼统了,不过我会尝试:
是否有关于通用Lisp类型的全面指南?

我对此主题感到困惑:

为什么将make-array:element-type中声明的非原始类型提升为t?是否有可能对实际声明的类型进行编译时或运行时检查?

为什么CLOS插槽定义的类型不能用作约束,而允许将任何类型的值放入插槽?再次,检查如何?

带有declare的函数类型声明是相同的。它们只是对编译器的优化提示吗?

另外,我是否可以使用自定义类型说明符,包括前面提到的位置的satisfies进行一些健壮的检查,或者只能将它们用于typep e.t.c的显式检查?

如您所见,我头脑有些困惑,因此,非常感谢任何简洁的指南(或一组指南)。

我在SBCL上工作,但也很高兴了解实现之间的差异。

最佳答案

如果您希望编译器实际执行这些类型,则需要告诉编译器进行安全性优化:

CL-USER> (declaim (optimize (safety 3)))
NIL
CL-USER> (defclass foobar () ())
#<STANDARD-CLASS COMMON-LISP-USER::FOOBAR>
CL-USER> (defun foo (a)
           (make-array 1 :element-type 'foobar
                         :initial-contents (list a)))
FOO
CL-USER> (foo (make-instance 'foobar))
#(#<FOOBAR {1005696CE3}>)
CL-USER> (foo 12)
;=> ERROR
CL-USER> (declaim (ftype (function (integer integer) integer) quux))
(QUUX)
CL-USER> (defun quux (a b)
           (+ a b))
QUUX
CL-USER> (quux 12 12)
24 (5 bits, #x18, #o30, #b11000)
CL-USER> (quux 12 "asd")
;=> ERROR

在运行时检查类型会增加一些开销(特别是如果它是在循环中发生的),并且对于单个值可能会多次执行,因此默认情况下不会执行此操作。
(declaim (optimize (safety 3)))

(defun some-predicate-p (a)
  (format t "~&Checking type...")
  (integerp a))

(deftype foo () `(satisfies some-predicate-p))

(defclass bar ()
  ((foo :type foo :initarg :foo)))

(declaim (ftype (function (foo) list) qwerty))
(defun qwerty (foo)
  (loop repeat 10 collecting (make-instance 'bar :foo foo)))

(qwerty 12)
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
; Checking type...
;=> (#<BAR {1003BCA213}> #<BAR {1003BCA263}> #<BAR {1003BCA2B3}>
;    #<BAR {1003BCA303}> #<BAR {1003BCA353}> #<BAR {1003BCA3A3}>
;    #<BAR {1003BCA3F3}> #<BAR {1003BCA443}> #<BAR {1003BCA493}>
;    #<BAR {1003BCA4E3}>)

如果希望函数始终检查场所的类型,而不考虑优化设置,则应手动使用 CHECK-TYPE

关于types - 常见口臭类型的综合指南,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37705393/

相关文章:

c++ - 在cygwin的makeing(编译)代码上,make命令告诉我我需要“ver”和“type”命令

c++ - 使用精确大小的整数c++

lisp - 列表之间的两个公共(public)元素

c++ - Qt信号/插槽问题

list - 区 block 链是单链表吗?

lisp - 在 lisp 编程中返回一个值

lisp - 负载提升包出现问题

python - Python 中的属性访问 : first slots, 然后 __dict__?

c++ - 为什么Qt默认信号是公开的?

list - 如果使用 "+"运算符添加列表,为什么 Kotlin 会将 List<List<Int>> 类型的列表更改为 List<Any>?