Pergunta

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)).

Foi útil?

Solução

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.

Outras dicas

You declare that rowlist is a vector (but treat it is a list — using last and first). This means that the compiler assumes that the object you pass to it is a vector, so, when you pass it a list, you get undefined behavior.

The most important thing to know about declarations in Lisp is: do not lie to the compiler. I.e., if you violate your declarations (like you just did), you will get burned.

(Additionally, you do not need to eval nil, and there is no need for the let* since you are using the variables it binds just once).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top