Вопрос

Я пытаюсь запустить код трассировки лучей от Пола Грэхема ANSI Common Lisp ( общий лисп ) в OS X используется SLIME с OpenMCL (ну, теперь называется CCL).В этом коде определена константа, значением которой является структура, и когда я вызываю либо slime-скомпилировать и загрузить файл или слизь-компиляция-удаление при любой функции, использующей константу, я получаю сообщение об ошибке:

Метод MAKE-LOAD-FORM не определен для #S(ТОЧКА: X 0 :Y 0 :Z 200) [Условие типа ПРОСТОЕ-ОШИБКА]

Я нашел сообщение объяснение сложности и еще один сожалею об этом, но что нужно добавить в код, чтобы согласовать этот аспект OpenMCL?

Это было полезно?

Решение

Когда СТРУКТУРНЫЕ объекты (и некоторые другие типы объектов) отображаются как литеральные, постоянные объекты в коде, обрабатываемом COMPILE-FILE, COMPILE-FILE должен знать, как организовать, чтобы при загрузке результирующего двоичного файла создавался "эквивалентный" объект.Существует множество возможных определений термина "эквивалентный". :иногда важно, чтобы компоненты загруженного объекта совместно использовали структуру с другими объектами, иногда важно, чтобы инициализация происходила определенным образом, а иногда ни одна из этих вещей не важна.Чтобы определить, как воссоздать постоянный объект, COMPILE-FILE вызывает универсальную функцию MAKE-LOAD-FORM;это поведение должно быть описано в любом справочнике CL или учебном пособии.(В справочнике или руководстве следует также отметить, что реализация не может определить методы MAKE-LOAD-FORM по умолчанию, которые были бы применимы ко всем экземплярам STRUCTURE-CLASS или STANDARD-CLASS, а также следует отметить, что MAKE-LOAD-FORM-SAVING-SLOTS - это удобная функция для использования в методах MAKE-LOAD-FORM для объектов, инициализация которых не должна быть сложной, например:

(defmethod make-load-form ((p point) &optional env)
  (declare (ignore env))
  (make-load-form-saving-slots p))

Обратите внимание, что этот метод должен быть определен во время компиляции, чтобы COMPILE-FILE мог вызвать его, чтобы определить, как сохранить объект constant POINT.

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

В коде, подобном:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () a-point)

компилятору разрешено (но не обязательно) заменять значение A-POINT ссылкой на него в функции RETURN-A-POINT.(Если компилятор сделает это, это будет означать, что в компилируемом коде есть объект literal / constant POINT , и COMPILE-FILE потребуется вызвать MAKE-LOAD-FORM, чтобы определить, как объект должен быть сохранен и загружен;если компилятор не выполняет эту замену, то MAKE-LOAD-FORM не нужно вызывать в этом примере.)

Выполняет ли реализация такого рода замену или нет, зависит от реализации.Спецификация также оставляет неуказанным, вычисляется ли форма значения в DEFCONSTANT форме во время компиляции, во время загрузки или и то, и другое, и отмечает, что необходимо проявлять осторожность (пользователем), чтобы гарантировать, что выражение всегда принимает одно и то же значение.

CCL обычно пытается оценить форму значения DEFCONSTANT во время компиляции и довольно агрессивно относится к замене значений именованных констант ссылками на них;в некоторых случаях это означает, что должны быть определены методы MAKE-LOAD-FORM для классов значений констант.Другие реализации могут быть менее склонны выполнять эту замену для некоторых типов объектов.Обе стратегии верны, и переносимый код не может предположить, каким стратегиям следуют (хотя большая часть якобы переносимого кода, несомненно, делает такие предположения).

Различное отношение к вещам, определенным DEFCONSTANT, кажется наиболее вероятной причиной такого рода вещей (неожиданные вызовы MAKE-LOAD-FORM, которые никто не потрудился определить).Можно избежать некоторых из этих проблем способом, который должен быть переносимым, выполнив:

(defconstant a-point (make-point :x 0 :y 0 :z 200))

(defun return-a-point () (load-time-value (symbol-value 'a-point)))

Это будет иметь эффект, аналогичный тому, чтобы просто разрешить реализации, которая хочет сделать это (как это делает CCL), выполнять подстановку констант, но использование LOAD-TIME-VALUE гарантирует, что постоянное значение вычисляется только во время загрузки (и что MAKE-LOAD-FORM задействован не будет).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top