Reputation: 954
I just read up on types in CL and I find the following behavior e.g. concerning subsidiary type information on the vector type a bit puzzling:
(let ((v1 (vector 1 3))
(v2 (vector 1 3 4))
(v3 (vector 1 3 "4")))
(values
(typep v1 '(vector (satisfies oddp)))
(typep v2 '(vector (satisfies oddp)))
(typep v3 '(vector (satisfies oddp)))))
According to the spec the first parameter to the vector compound type denotes the element-type, thus the type specifiers above should match a vector with elements that satisfy oddp
, right? So why are all type checks t then?!?! @_@
A solution to this could be
(defun vector-of-oddints-p (v)
(and
(vectorp v)
(every #'(lambda (n) (and (integerp n) (oddp n))) v)))
(let ((v1 (vector 1 3))
(v2 (vector 1 3 4))
(v3 (vector 1 3 "4")))
(values
(typep v1 '(satisfies vector-of-oddints-p))
(typep v2 '(satisfies vector-of-oddints-p))
(typep v3 '(satisfies vector-of-oddints-p))))
yet this feels clunky and the above type specifier should work imo.
Upvotes: 1
Views: 92
Reputation: 954
Thank you @Halbert and @Rainer Joswig; I learned something about arrays today! <3
The type specifier '(vector (satisfies oddp))
thus actually denotes a vector that can (but not necessarily and not exclusively has to) hold elements that satisfy the oddp predicate.
(cf. Rainer's answer: https://stackoverflow.com/a/21066478/6455731)
Unsurprisingly the spec is actually very educational on this:
If element-type is the symbol *, arrays are not excluded on the basis of their element type. Otherwise, only those arrays are included whose actual array element type is the result of upgrading element-type.
Also the section on array upgrading is informative, e.g. concerning the above mentioned "actual array element type":
During creation of an array, the element type that was requested is called the expressed array element type. The upgraded array element type of the expressed array element type becomes the actual array element type of the array that is created.
Upvotes: 3