Вопрос

Я пишу некоторые методы для излучения HTML для различных элементов. Каждый метод имеет одинаковый выход, но не обязательно нужен один и тот же вход.

Метод повторяет game-board нужно взять player Также (потому что каждый игрок видит только свои собственные произведения)

(defmethod echo ((board game-board) (p player)) ... )

Повторять пространство доски не требует изменения на одного игрока (эта диспетчерская на самом деле сделана в game-board Метод, который позже вызывает echo на пространстве). В идеале я смог бы сделать

(defmethod echo ((space board-space)) ... )
(defmethod echo ((space empty-space)) ... )

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

The generic function #<STANDARD-GENERIC-FUNCTION ECHO (4)> takes 2 required arguments;

Кажется не идеальным, чтобы вернуться и назвать эти методы echo-space, echo-board и так далее.

Есть ли канонический способ различения других аргументов на основе специализированного объекта? Должен ли я сделать что -то вроде

(defgeneric echo (thing &key player ...) ...)

или же

(defgeneric echo (thing &rest other-args) ...)

? В целом, может ли кто -нибудь указать мне на достойный учебник на defgeneric конкретно? (Я прочитал соответствующие главы PCL и немного Закрытый Учебные пособия, но они не покрывают ситуацию, о которой я прошу здесь).

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

Решение

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

Книга Кин Я считаю, что самое всеобъемлющее руководство для Clos. К сожалению, это кажется доступным только в форме книги.

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

Это проще, когда методы принимают одинаковые параметры, но различаются только на типе данных. Но в тех случаях, когда общая функция и методы все используют одно и то же имя (конечно), но в них есть списки Lambda, которые значительно различаются, я лично склонен использовать и ключевые параметры, чтобы сделать мои намерения явными, а не использование и необязательные параметры. Я думаю, что это помогает с читаемости позже.

Попробуйте что-то подобное (притворяясь, что у нас уже есть классы класса A и Class-B):

(defgeneric foo (object &key &allow-other-keys)
  (:documentation "The generic function. Here is where the docstring is defined."))

(defmethod foo ((object class-a) &key &allow-other-keys)
  (print "Code goes here. We dispatched based on type Class A."))

(defmethod foo ((object class-b) &key (x 1) (y 2) &allow-other-keys)
  (print "Code goes here. We dispatched based on type Class B. We have args X and Y."))

Поскольку «комбинация методов» задействована, чтобы логика диспетчеризации «тела» через его возможный выбор методов для использования, нам необходимо подумать о определениях метода, как цепь, где несовместимые списки лямбда (IE списки параметров) разорвутся эта цепь. Вот почему в определениях методов, которые они конкретно не нуждаются в том, что в определениях методов, которые они конкретно не нужны. Поместить их в DefEreneric и определения метода позволяет нам иметь определение метода, в котором мы отправляем на основе класса-B.

Отказ от ответственности: я сам обычный новичок LISP, так что возьмите это с зерном соли!

Как насчет реструктуризации объектов/классов, чтобы каждый объект, который вы хотите повторить, имел все необходимые свойства в своих (и унаследованных) слотах?

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

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