У меня есть файл R
и два файла A
, B
.
R
всегда загружен.
A
xor B
загружаются в зависимости от особенностей платформы. У меня есть функция, которая должна существовать независимо от платформы, назовите ее F
.
Каковы преимущества/недостатки использования:
DEFGENERIC
на F
в R
, затем DEFMETHOD
на F
в обоих A
, B
DEFUN
на F
в обоих A
, B
'На первый взгляд они должны быть одинаковыми. Это больше, чем вопрос предпочтений?
Обновлено: Реализации F
в A
и B
различны.
В настоящее время я использую первый метод, поскольку он дает понять, что функция является универсальной и имеет реализации, но мне любопытно, почему это имеет такое большое значение по сравнению со вторым методом.
Всегда ли F
имеет одну и ту же реализацию независимо от платформы? Если да, то почему бы не использовать defun
в R
?
@adabsurdum Это не так, иначе не было бы никакого смысла писать это дважды для каждой реализации. Я должен был прояснить это.
По моему мнению, преимущества или недостатки использования defgeneric
или defun
в вашем случае не отличаются от общего случая, а это означает, что здесь нет дополнительных ограничений по сравнению с обычным выбором между общими функциями и обычными.
Вообще говоря, функции проще и, возможно, более эффективны в использовании, поскольку к ним меньше требований (нет диспетчеризации, нет комбинации методов и т. д.), хотя на практике существует множество оптимизаций, которые делают это различие менее важным.
Общие функции могут помочь вам, если у вас есть платформа A'
, почти такая же A
, но с некоторыми изменениями, и в этом случае вы можете специализировать некоторые методы.
В своем вопросе вы рассматриваете два варианта, но учтите, что этим вы не ограничиваетесь. Посмотрите, например, как Слизь
определяет два макроса, definterface
и defimplementation
, для регистрации набора необходимых серверных функций и их реализаций на различных платформах.
Вы также можете посмотреть различные библиотеки, называемые по соглашению trivial-*stuff*
, которые объединяют различный код, специфичный для реализации, для выполнения *stuff*
в едином интерфейсе.
Универсальные функции в Common Lisp реализуют полиморфизм, известный в других объектно-ориентированных языках, где подтипы (или просто другие типы) могут реализовывать или переопределять обычно определенный интерфейс или протокол. Таким образом, семантически существует разница с простыми функциями.
С практической стороны, с точки зрения тестирования, cl-mock может имитировать только функции, но не общие функции. Для них вам придется создать типы тестов и реализовать конкретные тестовые реализации для тех, которые используются в тестах. Но, возможно, для вас это не актуально.
Если вещь будет иметь только одну реализацию в данном изображении, сделайте ее функцией. Если у нее может быть более одного метода или если реализация может быть распределена по нескольким методам, сделайте ее универсальной функцией с методами.
Я бы использовал универсальную функцию, когда функция должна быть расширяемой или иметь несколько реализаций одновременно. Здесь похоже это не так -> достаточно простой функции.