В общем, как я могу переопределить / изменить поведение оценки для определенного типа объекта? - PullRequest
3 голосов
/ 02 июня 2011

В Common-LISP я хочу реализовать такую ​​систему отсчета, как это:

Предположим, что у меня есть:

(defclass reference () ((host) (port) (file)))

, а также у меня есть:

(defun fetch-remote-value (reference) ...), который извлекает и десериализует объект lisp.

Как я могу вмешаться в процесс оценки, чтобы при оценке эталонного объекта удаленное значение извлекалось и повторно получалосьоценили еще раз, чтобы получить окончательный результат?

РЕДАКТИРОВАТЬ:

Более подробное описание того, что я хочу сделать:

Используя cl-store, я сериализую объекты lisp и отправляю их в удаленный файл (или db иличто угодно) быть спасенным.После успешного хранения я сохраняю хост, порт и файл в ссылочном объекте.Я хотел бы, чтобы всякий раз, когда eval вызывался для ссылочного объекта, сначала извлекал объект, а затем вызывал eval для полученного значения.Поскольку ссылку можно также сериализовать в других (родительских) объектах или агрегатных типах, я могу получить бесплатное рекурсивное разрешение удаленной ссылки, изменив eval, поэтому мне не придется самостоятельно просматривать и разрешать дочерние ссылки загруженного объекта.

РЕДАКТИРОВАТЬ: Поскольку объекты всегда оценивают сами себя, мой вопрос немного ошибочно задан.По сути, я хотел бы сделать следующее:

Я хотел бы перехватить оценку символов так, чтобы, когда их значение было объектом типа REFERENCE, вместо того, чтобы возвращать объект как результат оценки символа, вернутьрезультат (fetch-remote-value object)?

Ответы [ 4 ]

2 голосов
/ 03 июня 2011

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

MOP может использоваться для реализации отложенных или постоянных объектов, хотя значения слотов прозрачно форсируются. Для обеспечения общей прозрачности потребовалось бы изменить внутреннюю часть реализаций Common Lisp, чтобы вы могли сделать, например, (+ p 5) с p потенциально может иметь постоянное или ленивое значение.

2 голосов
/ 02 июня 2011

Короче говоря: вы не можете сделать это, кроме как переписав функцию eval и изменив компилятор вашего Lisp. Правила оценки зафиксированы стандартом Лисп.

Редактировать После прочтения расширенного вопроса, я не думаю, что вы можете достичь полной прозрачности для своих ссылок здесь. В сценарии, подобном

(defclass foo () (reference :accessor ref))
(ref some-foo)

Результатом обращения к ref является просто значение; он не будет рассматриваться для оценки независимо от его типа.

Конечно, вы можете определить свои методы доступа таким образом, чтобы разрешение было прозрачным:

(defmacro defresolver (name class slot)
    `(defmethod ,name ((inst ,class))
        (fetch-remote-reference (slot-value inst ',slot))))

(defresolver foo-reference foo reference)

Редактировать Вы можете (вроде) подключиться к механизму разрешения символов Common Lisp, используя макросы символов:

(defmacro let-with-resolution (bindings &body body) 
    `(symbol-macrolet ,(mapcar #'(lambda (form) (list (car form) `(fetch-aux ,(cadr form)))) bindings) ,@body))

(defmethod fetch-aux ((any t)) any)
(defmethod fetch-aux ((any reference)) (fetch-remote-reference any))

Однако теперь все становится довольно загадочным; и переменные уже не переменные, а магические символы, которые просто выглядят как переменные. Например, изменение содержимого переменной «связанный» этим макросом невозможно. Лучшее, что вы можете сделать с этим подходом, - это предоставить расширение setf для fetch-aux, которое изменяет исходное место.

1 голос
/ 05 июня 2011

Невозможно напрямую изменить механизмы оценки.Вам нужно написать компилятор для вашего кода для чего-то еще.Вид встроенного языка.

На уровне CLOS есть несколько способов справиться с этим:

Два примера:

  • написать функции, которые отправляютдля эталонного объекта:

    (перемещение defmethod (позиция объекта)) (перемещение (позиция разыменования))

    (перемещение defmethod (автомобиль объекта)) ...))

Это выглядит ужасно и может быть автоматизировано с помощью макроса.

Объекты CLOS уже имеют косвенное направление, потому что они могут изменить свой класс.Даже если они могут изменить свой класс, они сохраняют свою идентичность.CHANGE-CLASS деструктивно модифицирует экземпляр.

Так что это позволило бы обойти эталонные объекты и в какой-то момент загрузить данные, изменить эталонный объект на какой-то другой класс и соответственно установить слоты.Это изменение класса должно быть инициировано где-то в коде.

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

0 голосов
/ 02 июня 2011

Я бы добавил слой поверх вашего механизма десериализации, который отправляет в зависимости от типа входящих данных.

...