Объявления типов Common Lisp не работают должным образом

Когда я определяю функцию в Common Lisp следующим образом:

(defun foo (n)
  (declare (type fixnum n))
  (+ n 42))

Я ожидал, что такой вызов, как (foo "a"), сразу же потерпит неудачу, но вместо этого он потерпит неудачу при вызове +. Разве форма declare не гарантирует статическую проверку типов?


person Eli Schneider    schedule 01.03.2012    source источник


Ответы (2)


Объявления типов традиционно предназначены для использования в качестве гарантий для компилятора в целях оптимизации. Для проверки типов используйте check-type (но обратите внимание, что он также выполняет проверку во время выполнения, а не во время компиляции):

(defun foo (n)
  (check-type n fixnum)
  (+ n 42))

Тем не менее, разные реализации Common Lisp интерпретируют объявления типов по-разному. SBCL, например, будет рассматривать их как типы, подлежащие проверке, если safety настройка политики достаточно высока.

Кроме того, если вам нужна статическая проверка, SBCL, вероятно, также является лучшим выбором, поскольку его механизм вывода типов предупреждает вас о любых несоответствиях, с которыми он сталкивается. С этой целью объявления ftype могут быть использованы с пользой:

CL-USER(1): (declaim (ftype (function (string) string) bar))

CL-USER(2): (defun foo (n)
              (declare (type fixnum n))
              (bar n))
; in: DEFUN FOO
;     (BAR N)
; 
; caught WARNING:
;   Derived type of N is
;     (VALUES FIXNUM &OPTIONAL),
;   conflicting with its asserted type
;     STRING.
;   See also:
;     The SBCL Manual, Node "Handling of Types"
; 
; compilation unit finished
;   caught 1 WARNING condition

FOO
person Matthias Benkard    schedule 01.03.2012

Объявления — это просто подсказки для компилятора, чтобы он мог создавать более эффективный код. Другими словами, это не статическая проверка.

person zvrba    schedule 01.03.2012