在 Lisp 中,如果值不是具有所有整数键和值的散列 table,您能否构造一个抛出错误的“check-type”?
In Lisp, can you construct a `check-type` that throws an error if the value is not a hash-table with all integer keys and values?
假设我有一个函数:
(defun distribution-to-list (distribution)
(check-type distribution hash-table)
(loop for key being each hash-key of distribution
using (hash-value value) nconc (loop repeat value collect key)))
我想确保至少传入的 hash-table 的所有值都是整数,因为我使用它们将值重复到一个大列表中。有什么办法可以在内循环之前使用 check-type
吗?或者让内部循环宏在尝试 repeat
字符串时抛出类型错误是否足够好? (或任何非整数类型)
如果你能写一个函数来检查一个值是否可以接受,那么你可以使用satisfies构造一个类型说明符,比如(satisfies is-acceptable)
。例如,
(defun all-integer-keys-p (ht)
(loop for k being each hash-key in ht
always (integerp k)))
(let ((h (make-hash-table)))
;; when the table contains only integer
;; keys, we're fine
(setf (gethash 1 h) 'foo
(gethash 2 h) 'bar)
(check-type h (satisfies all-integer-keys-p))
;; but a non-integer key will lead to an
;; error from CHECK-TYPE
(setf (gethash 'three h) 'baz)
(check-type h (satisfies all-integer-keys-p)))
使用 deftype,您可以为 (satisfies all-integer-keys-p)
定义一个类型 shorthand,您可能会发现这样更易读:
(deftype all-integer-key-hash-table ()
`(satisfies all-integer-keys-p))
(let ((h (make-hash-table)))
(setf (gethash 1 h) 'foo
(gethash 2 h) 'bar)
(check-type h all-integer-key-hash-table)
(setf (gethash 'three h) 'baz)
(check-type h all-integer-key-hash-table))
假设我有一个函数:
(defun distribution-to-list (distribution)
(check-type distribution hash-table)
(loop for key being each hash-key of distribution
using (hash-value value) nconc (loop repeat value collect key)))
我想确保至少传入的 hash-table 的所有值都是整数,因为我使用它们将值重复到一个大列表中。有什么办法可以在内循环之前使用 check-type
吗?或者让内部循环宏在尝试 repeat
字符串时抛出类型错误是否足够好? (或任何非整数类型)
如果你能写一个函数来检查一个值是否可以接受,那么你可以使用satisfies构造一个类型说明符,比如(satisfies is-acceptable)
。例如,
(defun all-integer-keys-p (ht)
(loop for k being each hash-key in ht
always (integerp k)))
(let ((h (make-hash-table)))
;; when the table contains only integer
;; keys, we're fine
(setf (gethash 1 h) 'foo
(gethash 2 h) 'bar)
(check-type h (satisfies all-integer-keys-p))
;; but a non-integer key will lead to an
;; error from CHECK-TYPE
(setf (gethash 'three h) 'baz)
(check-type h (satisfies all-integer-keys-p)))
使用 deftype,您可以为 (satisfies all-integer-keys-p)
定义一个类型 shorthand,您可能会发现这样更易读:
(deftype all-integer-key-hash-table ()
`(satisfies all-integer-keys-p))
(let ((h (make-hash-table)))
(setf (gethash 1 h) 'foo
(gethash 2 h) 'bar)
(check-type h all-integer-key-hash-table)
(setf (gethash 'three h) 'baz)
(check-type h all-integer-key-hash-table))