I am trying to dispatch on the type of an array. Here's a test case:
(defun column-summary2 (column)
(typecase column
(simple-double-float-vector (format t "Column is a simple-double-float-vector~%"))
;; (simple-integer-vector (format t "Column is a simple-integer-vector~%"))
;; (simple-string-vector (format t "Column is a simple-string-vector~%"))
((simple-array string (*)) (format t "~A Column is a string-array~%" column))
((simple-array float (*)) (format t "~A is a simple-float-array~%" column))
((simple-array integer (*)) (format t "~A is a simple-float-array~%" column))
(bit-vector (make-bit-vector-summary :length (length column) :count (count 1 column))))))
This works as expected for the built in type, bit-vector, and with my own simple-double-float-vector type:
(deftype simple-double-float-vector (&optional (length '*))
"Simple vector of double-float elements."
`(simple-array double-float (,length)))
but fails for string and integer:
LS-USER> (df::column-summary2 #("foo" "bar" "baz"))
#(foo bar baz) Column is a string-array
NIL
LS-USER> (df::column-summary2 #(1 2 3))
#(1 2 3) Column is a string-array
I tried defining types for these two:
(deftype simple-integer-vector (&optional (length '*))
"Simple vector of integer elements."
`(simple-array integer (,length)))
(deftype simple-string-vector (&optional (length '*))
"Simple vector of integer elements."
`(simple-array string (,length)))
Edit: Coerce also seems to fail:
CL-USER> (type-of (coerce #(4 4 1 1 2 1 4 2 2 4 4 3 3 3 4 4 4 1 2 1 1 2 2 4 2 1 2 2 4 6 8 2) '(simple-array integer (32))))
(SIMPLE-VECTOR 32)
CL-USER> (type-of (coerce #("foo" "bar" "baz") '(simple-array string (3))))
(SIMPLE-VECTOR 3)
but it doesn't help. It seems that integer and string are always conflated. Can anyone see why?
typecase can only distinguish types that are implementationally distinct, and it is very unlikely that arrays of integers and strings are. You can test this by, for instance:
(eq (upgraded-array-element-type 'integer)
(upgraded-array-element-type 'string))
Which will very likely return t. And in fact it's likely that upgraded-array-element-type on both these types is itself t: the most specialised array that can store a general string is the same as the one that can store a general integer, since both of these types really require the elements of the array to be general pointers.
The thing here is that when typecase sees an array all it can dispatch on is the implementational type of the array, rather than anything else and those two types are the same in many cases where they are not the same conceptually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With