Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In common lisp, how can I check the type of an object in a portable way

I want to define a method that will specialize on an object of array type with unsigned byte 8 elements. In sbcl, when you (make-array x :element-type '(unsigned-byte 8)) the object class is implemented by SB-KERNEL::SIMPLE-ARRAY-UNSIGNED-BYTE-8. Is there an implementation independent way of specializing on unsigned-byte array types?

like image 381
Paralife Avatar asked May 21 '11 17:05

Paralife


People also ask

Does Common Lisp have types?

Common Lisp has a complete and flexible type system and corresponding tools to inspect, check and manipulate types. It allows creating custom types, adding type declarations to variables and functions and thus to get compile-time warnings and errors.

What are the only two types of values in Lisp?

Numbers are represented by the symbol number. Lisp has two types of numbers: integer and floating-point.

Which keyword is used to access the elements of array in Lisp?

In LISP, an array element is specified by a sequence of non-negative integer indices. The length of the sequence must equal the rank of the array. Indexing starts from zero. The aref function allows accessing the contents of the cells.

Is lisp a generic?

A generic function is a lisp function which is associated with a set of methods and dispatches them when it's invoked. All the methods with the same function name belong to the same generic function. The defmethod form is similar to a defun .


2 Answers

Use a sharpsign-dot to insert the implementation dependent object class at read-time:

(defmethod foo ((v #.(class-of (make-array 0 :element-type '(unsigned-byte 8)))))
  :unsigned-byte-8-array)

The sharpsign-dot reader macro evaluates the form at read-time, determining the class of the array. The method will be specialized on the class the particular Common Lisp implementation uses for the array.

like image 90
Terje Norderhaug Avatar answered Oct 22 '22 09:10

Terje Norderhaug


Notice that the :ELEMENT-TYPE argument to MAKE-ARRAY does something special and its exact behavior might be a bit surprising.

By using it, you are telling Common Lisp that the ARRAY should be able to store items of that element type or some of its subtypes.

The Common Lisp system then will return an array that can store these elements. It may be a specialized array or an array that can also store more general elements.

Notice: it is not a type declaration and it will not necessarily be checked at compile or runtime.

The function UPGRADED-ARRAY-ELEMENT-TYPE tells you what element an array may actually be upgraded to.

LispWorks 64bit:

CL-USER 10 > (upgraded-array-element-type '(unsigned-byte 8))
(UNSIGNED-BYTE 8)

CL-USER 11 > (upgraded-array-element-type '(unsigned-byte 4))
(UNSIGNED-BYTE 4)

CL-USER 12 > (upgraded-array-element-type '(unsigned-byte 12))
(UNSIGNED-BYTE 16)

So, Lispworks 64bit has special arrays for 4 and 8 bit elements. For 12 bit elements it allocates an array which can store up to 16bit elements.

We generate an array which can store ten numbers of upto 12 bits:

CL-USER 13 > (make-array 10
                         :element-type '(unsigned-byte 12)
                         :initial-element 0)
#(0 0 0 0 0 0 0 0 0 0)

Let's check its type:

CL-USER 14 > (type-of *)
(SIMPLE-ARRAY (UNSIGNED-BYTE 16) (10))

It is a simple array (non-adjustable, no fill pointer). It can store elements of type (UNSIGNED-BYTE 16) and its subtypes. It is of length 10 and has one dimension.

like image 44
Rainer Joswig Avatar answered Oct 22 '22 07:10

Rainer Joswig