I'm new to Lisp. I've heard that it's possible to declare the type of variables in Lisp. I find declaring types very useful, since it allows to detect many errors during the compilation process. I've read, though, that in SBCL declarations are simply assertions, which are checked at the runtime.

I'm new to Lisp. I've heard that it's possible to declare the type of variables in Lisp. I find declaring types very useful, since it allows to detect many errors during the compilation process. I've read, though, that in SBCL declarations are simply assertions, which are checked at the runtime.

If so, how can one use static typing in Common Lisp?

Not quite. Declarations are checked at compile-time as much as they can be and the compiler will generate an error if it finds a conflict. With multiple compilation modules, runtime code generation, etc., this cannot be a perfect net, however. Thus, type errors can still occur. (I'd note that with things like untyped pointers, this can occur even in static languages like C.)

So, to help deal with these situations gracefully, SBCL will insert runtime type checking code to confirm that particular types are as you have declared them. If you violate the typing, the checks will catch it and throw you into the debugger as punishment, but the Lisp image will still be up and stable and you can debug appropriately. This is done for standard levels of speed and safety. Now, if you tell the compiler that you want high speed and no safety, it will produce code that eliminates these checks and simply believes whatever you tell it, with the consequence of a crash if it turns out later that you lied. It's a tradeoff. For anything other than small inner loops, I wouldn't do this. I'd rather have the system running if I make a mistake in order to debug and you'll get far more speedup algorithmically than you will from eliminating type checking in most cases.

findinglisp wrote:Not quite. Declarations are checked at compile-time as much as they can be and the compiler will generate an error if it finds a conflict. With multiple compilation modules, runtime code generation, etc., this cannot be a perfect net, however. Thus, type errors can still occur. (I'd note that with things like untyped pointers, this can occur even in static languages like C.)

This seems to be one of the biggest misunderstandings in the classical strong static typing camps. The conservative view is that compilation is always a phase before the program is run. A program - once compiled - cannot change in unforeseen ways. I've discussed this topic extensively with guys seeing themselves as field experts - it really doesn't seem to click in.

The strict order of lifetime phases of a program are less strict in common lisp. It is easy to create programs that compile or load things within the running program. One consequence of this is that obvious bugs could be fixed through code build or loaded at runtime. So if you compile a common lisp function like this:

For the hardcore conservativists in the static types field this means that nothing is safe. The reality is actually quite different: A good common lisp implementation has all information set to issue a warning. The simple consequence is that a common lisp programmer should have an even bigger eye on issued warnings: A good rule of thumb is that a warning in common lisp is often a sign for a bug that could cancel compilation in more strict and conservative static languages; it's a clear signal that one should re-check the code. Non-critical warnings are issued as "style warnings" in common lisp.

To me - this property of common lisp makes it actually more robust and more safe than the brittle compile once crash everywhere attitude of other systems.