Search code examples
common-lisplispworks

Why does this function crash LispWorks?


When I run this function from a listener in LispWorks, it either crashes the listener or gives an exception and assembly language data. Can anyone tell me what's wrong with it?

(defun should-flip-block (rowlist)
  (declare ((vector number) rowlist))
  (if (= (length rowlist) 0) (eval nil) 
    (let* ((exithigh (= (car (last rowlist)) 2))
           (enterhigh (= (first rowlist) 2)))  
      (and exithigh enterhigh))))

It's called as (should-flip-block '(1 2 1 2 1)).


Solution

  • Problematic declaration

    Note that not all Common Lisp implementations will think that (declare ((vector number)) rowvector) is a valid declaration.

    Write instead (declare (type (vector number) rowvector)).

    Wrong: a list is not a vector

    The problems you see is because you lied to the implementation and safety is set low. You told Lisp that the argument is a vector, but you pass a list (which is not a vector).

    The function then use calls to FIRST and LAST, which don't work on vectors, but lists.

    Run code with higher safety value

    Don't run Common Lisp by default with low safety. Use a default safety value of 2 or 3.

    Using LispWorks 6.1.1:

    CL-USER 43 > (proclaim '(optimize (safety 2)))
    NIL
    

    now I recompile the function and then call it:

    CL-USER 44 > (should-flip-block '(1 2 1 2 1))
    
    Error: Variable ROWLIST was declared type (VECTOR NUMBER) but is being
           bound to value (1 2 1 2 1)
      1 (abort) Return to level 0.
      2 Return to top loop level 0.
    

    Now you see an useful error and not a segment violation.

    Literal Vectors

    #(1 2 1 2 1) is a vector.

    Note: LIST type has no parameter

    Note that a type (list number) does not exist in Common Lisp and can't be defined. The type list can't have a parameter. It's also not possible to define such a type based on the type cons - recursive types don't work.