Как я могу сделать SetF в агрегатах структуры при использовании стажеров

StackOverflow https://stackoverflow.com/questions/3641509

  •  30-09-2019
  •  | 
  •  

Вопрос

Хотелось бы setf разные поля структуры в зависимости от определенной переменной. Я решил использовать следующий подход:

Создайте строку с именем аксера поля:

(setq my-string (format nil "STRUCT-ESTADISTICAS-NUM-~S" x))

а затем использовать стажер с Funcall:

(funcall (intern my-string) *estadisticas*)

Этот вызов возвращает правильное значение поля структуры, но если я попробую setf Чтобы изменить это значение, которое он жалуется, говоря:

(setf (funcall(intern my-string) *estadisticas*) 0)
Error: `(SETF FUNCALL)' is not fbound

Я могу понять, почему это не работает, но я не могу найти способ изменить поля структуры. Есть идеи? Спасибо.

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

Решение

Вы хотите вызвать функцию писателя структуры через его имя, и имя писателя является список (setf accessor-name); так

(funcall (fdefinition (list 'setf (intern my-string))) 0 estadisticas)

Редактировать:

Не видя остальной части вашего кода, трудно понять, что пошло не так. На SBCL это работает для меня:

(defstruct point x y)
(let ((point (make-point :x 1 :y 2)))
  (funcall (fdefinition (list 'setf (intern "POINT-X"))) 10 point)
  point)

Вышеуказанное оценивается к

#S(POINT :X 10 :Y 2),

как и ожидалось.

Другие советы

Мотивация:

Структуры являются относительно низкоуровневым объектом. «Скорость» была важной целью дизайна. Воспредствие по функциям писателя не поддерживается стандартом (как я его прочитал). Сегодня, используйте в соответствии с по умолчанию, если не нуждается в лучшей эффективности структур (быстрее прочитанные и пишеты слотов со структурами иногда возможны).

Первый - стиль:

Не используйте стажер, используйте находки-символ. Также укажите пакет, в противном случае находки-символ будет использовать значение выполнения * Package * как пакет

Второе - расправка

Если я правильно прочитал стандарт ANSI CL, это не то, что Defstruct создает функции писателя для слотов, как DefClass.

CL-USER 24 > (defstruct foo bar baz)
FOO

CL-USER 25 > #'(setf foo-bar)

Error: Undefined function (SETF FOO-BAR) in form (FUNCTION (SETF FOO-BAR)).

Итак, построение такого имени (SETF FOO-BAR) и попытка найти функцию для этого, поскольку такая функция не существует определенной задачи.

То, что в пользовательском коде (SETF (Foo-bar некоторые struction) 42) работает, основано на определенных расширении SETF, предоставляемых дефструктом, но не на определенных функциях Accessior SetF.

Некоторые общие реализации LISP могут предоставить писателю функционировать как нестандартное расширение ANSI CL.

Возможные решения:

а) Используйте закрытые классы, DefClass делает то, что вы хотите

б) напишите писательские функции себя

(defun (setf foo-bar) (new-value struct)
   (setf (foo-bar struct) new-value))

Сейчас:

(funcall (fdefinition '(setf foo-bar)) 300 *foo*)

Выше потом работает.

c) (Setf Slot-значение) - еще одна нестандартная особенность некоторых реализаций.

В некоторых реализациях обычного Lisp это работает не только для закрытых классов, но и для структур:

(setf (slot-value some-struct 'bar) 42)

Я не уверен, что Allegro CL поддерживает это, но это было бы легко узнать.

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