Yesterday I wrote a simple implementation of dataframe. A dataframe stores data columns as simple vectors of some type.
For this implementation, I needed a type inference to set vector's type for each column. An inferred type should be generic enough to work for all items in the column.
But what if we have positive and negative integers in our data? What type will return the standard
Here is the answer:
POFTHEDAY> (type-of 21) (INTEGER 0 4611686018427387903) POFTHEDAY> (type-of -21) FIXNUM
So, if I'll make my vector's type
(INTEGER 0 4611686018427387903) it will raise an error on the second element:
POFTHEDAY> (make-array 2 :element-type '(INTEGER 0 4611686018427387903) :initial-contents '(21 -21)) ; Debugger entered on ; #<TYPE-ERROR expected-type: ; (UNSIGNED-BYTE 62) datum: -21>
That's why I started to search the way to make inferred type more generic and found
Here is how it works:
POFTHEDAY> (mapcar #'type-of '(21 -23 1.23 4.56d0 "string")) ((INTEGER 0 4611686018427387903) FIXNUM SINGLE-FLOAT DOUBLE-FLOAT (SIMPLE-ARRAY CHARACTER (6))) POFTHEDAY> (mapcar #'simplified-types:simplified-type-of '(21 -23 1.23 4.56d0 "string")) ((INTEGER 21 21) (INTEGER -23 -23) SINGLE-FLOAT DOUBLE-FLOAT T)
INTEGER with bounds still is not what I need for my application. Happily, Marco Heisig foresee this need and added a switcher which makes integer types more generic.
With this option, the library produces exactly what I need:
POFTHEDAY> (let ((simplified-types::*precise-integer-types* nil)) (mapcar #'simplified-types:simplified-type-of '(21 -23 1.23 4.56d0 "string"))) ((INTEGER * *) (INTEGER * *) SINGLE-FLOAT DOUBLE-FLOAT T)
If you'd like to work with types in Common Lisp, then you probably might be interested in the library I've reviewed recently - trivialib.type-unify. It allows us to do pattern-matching on type specifiers.