0
votes

I am studying Common Lisp and I would like to know if by using the :type slot in a defstruct, I am making the code more efficient?

In "Paradigms of Artificial Intelligence Programming", Peter Norvig wrote that with the appropriate declarations you can make Common Lisp programs as efficient as C programs. He writes that run-time type-checking is slow in Common Lisp but if you add declarations then you eliminate run-time checks.

So, I am aware that using the :type slot is analogous to a declaration of a variable so I would like to know if using :type makes the code faster (ie eliminates run time checks).

Here are some examples:

(defstruct matrix
   rows 
   columns 
   contents)

Here is the version with :type:

(defstruct matrix
  rows 
  columns 
  (contents (:type list)))

So does using :type eliminate run-time checks? or if it is possible how do you use :type to eliminate run-time checks?

I am working on a linear algebra system in Common Lisp and I would like to make it efficient. So, I am wondering if by doing (like above) (contents (:type list)) if the compiler is going eliminate the run-time check that the compiler would do if contents was not declared as a list.

Thanks

1

1 Answers

8
votes

The first thing that comes to mind is that this adds a runtime check. Now the runtime may check every time the slot is changed, that the change is compatible with the declared type. So adding such a type declaration will make code slower, because it by default will add a runtime check. But this depends on the capabilities of the compiler and the Lisp runtime.

Common Lisp has compilation qualities: speed, debug, safety, space and compilation-speed. Individual Common Lisp implementations may have additional qualities.

There might be a scenario where adding a type declaration for a slot may help:

  • let's say we have a function foo which has one argument: a single float number. The function adds 1.0 to the number.

  • then we may have a structure object which has a slot n, which is declared to be of type single float

The operation (foo (struct-n some-struct)) might then omit checks, if some combination of quality makes the compiler infer and check the types at compile time: it then might know that these are all single-float computations and that this can be determined at compile time -> it will generate single float instructions and will omit the runtime type checks.

A good compiler (like SBCL) might tell us that it has done such optimization (or that it can't do it for some reason). So from there we might know that runtime type checks have not be generated into the compiled code.

One can also use the function DISASSEMBLE and see if the generated code includes type checks or not.