SBCL-специфическая декламация - PullRequest
0 голосов
/ 12 сентября 2018

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

(declaim (sb-ext:muffle-conditions style-warning))

Недостатком является то, что CCL, по понятным причинам, блокирует программу, содержащую вышеуказанное.Я пытаюсь решить эту проблему с условным условием:

(#+sbcl (declaim (sb-ext:muffle-conditions style-warning)))

, но теперь SBCL недоволен: «незаконный вызов функции».

Как поместить такое объявление в переносимую программу?

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Обратите внимание, что, хотя существующий ответ правильный, отключение предупреждений не является хорошей практикой. В вашем случае это, вероятно, не нужно.

Common Lisp имеет понятие единицы компиляции, где несколько определений группируются вместе. Это дает возможность компилятору / интерпретатору позаботиться о перекрестных ссылках между функциями (например, интерпретатор может собирать предупреждения и сохранять только те, которые не найдены позже).

Например, в файле #P"/tmp/foo.pl":

(defun mut-rec-foo (x)
  (when (plusp x)
    (mut-rec-bar (1- x))))

(defun mut-rec-bar (x)
  (print x)
  (mut-rec-foo (1- x)))

Не оценивать ничего в файле; вместо этого:

(compile-file #P"/tmp/foo.pl")

; compiling (DEFUN MUT-REC-FOO ...)
; compiling (DEFUN MUT-REC-BAR ...)

; /tmp/foo.fasl written
; compilation finished in 0:00:00.002

Без предупреждения. Затем вы можете позвонить (load #P"/tmp/foo.fasl"), чтобы получить определения в вашей текущей среде lisp без предупреждений. Обычно ASDF и расширение Quicklisp используют COMPILE-FILE, поэтому ваша проблема должна исчезнуть, как только вы объедините свои файлы в систему.

Вы также можете сделать:

(with-compilation-unit ()
  (defun mut-rec-foo/bis (x)
    (when (plusp x)
      (mut-rec-bar/bis (1- x))))

  (defun mut-rec-bar/bis (x)
    (print x)
    (mut-rec-foo/bis (1- x))))

Оценка всего блока не показывает предупреждения для *EVALUATOR-MODE*, являющегося одновременно :COMPILE или :INTERPRET.

То, что вы засвидетельствовали, происходит, когда вы оцениваете каждое выражение одно за другим (или, может быть, один регион за другим). Там компилятор не может знать, что функция уже существует. Отключение предупреждения - худший вариант, потому что вы могли действительно сделать ошибку.

Если вы заранее знаете, что функция будет существовать, но не в вашем модуле компиляции (может быть, она определена только во время выполнения), вы можете объявить этот факт как следующим образом:

(declaim (ftype function my-function))

Выше сказано, что my-function должно быть принято fbound для объекта типа function. Вы также можете предоставить больше информации, уточнив, какую функцию вы заявляете:

(declaim (ftype (function (number) (values string &optional)) num-to-string))

... для функции, которая принимает число и возвращает ровно одно значение - строку.

(declaim (ftype (function () nil) forever-loop))

... для функции, которая ничего не принимает и никогда не возвращает значение (цикл или сигнализирует об ошибке).

0 голосов
/ 12 сентября 2018

Пропустите внешнюю пару скобок:

#+sbcl (declaim (sb-ext:muffle-conditions style-warning))

Поскольку вы используете declaim, я предполагаю, что объявление появляется на верхнем уровне единицы компиляции.Если вам нужно сгруппировать несколько операторов верхнего уровня, вы можете обернуть их всех символом progn (который не меняет "верхнего уровня").

Причина, по которой SBCL жаловалась, заключается в том, чточто читатель читает

((declaim (sb-ext:muffle-conditions style-warning)))

(так как присутствует функция :SBCL), что является просто синтаксической ошибкой.CCL не жалуется, потому что читатель читает

()

, что является просто еще одним способом заклинания nil.

...