Замена обычной функции универсальной функцией
Я хотел бы использовать такие имена, как elt, nth и mapcar, с новой структурой данных, которую я создаю на прототипе, но эти имена обозначают обычные функции, и поэтому, я думаю, их нужно будет переопределить как универсальные функции.
Предположительно, плохо переопределять эти имена?
Есть ли способ сказать defgeneric не генерировать программную ошибку и пойти дальше и заменить привязку функции?
Есть ли веская причина, по которой они не являются общими функциями или являются просто историческими?
В чем здесь мудрость и лучшая практика, пожалуйста?
2 ответа
Если вы используете SBCL или ABCL и не заботитесь о соответствии ANSI, вы можете исследовать расширяемые последовательности:
http://www.doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf
... вы не можете переопределить функции в пакете COMMON-LISP, но вы можете создать новый пакет и скрыть импорт функций, которые вы хотите переопределить.
Есть ли веская причина, по которой они не являются общими функциями или являются просто историческими?
Common Lisp имеет несколько уровней языка в некоторых своих областях. Части программного обеспечения более высокого уровня, возможно, должны быть построены на конструкциях более низкого уровня.
Одной из его целей было быть достаточно быстрым для целого ряда приложений.
Common Lisp также ввел идею последовательностей, абстракции над списками и векторами, в то время, когда язык не имел объектной системы. CLOS появился через несколько лет после первоначального дизайна Common Lisp.
Взять, к примеру, что-то вроде равенства - для чисел.
Лисп имеет =
:
(= a b)
Это самый быстрый способ сравнить цифры. =
также определяется только для чисел.
Тогда есть eql
, equal
а также equalp
, Они работают для чисел, но и для некоторых других типов данных.
Теперь, если вам нужна большая скорость, вы можете объявить типы и указать компилятору генерировать более быстрый код:
(locally
(declare (fixnum a b)
(optimize (speed 3) (safety 0)))
(= a b))
Итак, почему =
не универсальная функция CLOS?
а) оно было введено, когда CLOS не существовало
но не менее важно:
б) в Common Lisp не было известно (и до сих пор нет), как сделать универсальную функцию CLOS =
так быстро, как неуниверсальная функция для типичных сценариев использования - при сохранении динамической типизации и расширяемости
Общая функция CLOS просто имеет штраф за скорость. Расходы на отправку во время выполнения.
CLOS лучше всего использовать для кода более высокого уровня, который затем действительно получает преимущества от таких функций, как расширяемость, множественная диспетчеризация, наследование / комбинации. Универсальные функции должны использоваться для определенного универсального поведения, а не как наборы похожих методов.
С лучшей технологией реализации, улучшенными языками реализации и т. Д. Можно было бы увеличить диапазон кода, который может быть написан с использованием CLOS. Это было опробовано с такими языками программирования, как Дилан и Джулия.
Предположительно, плохо переопределять эти имена?
Обычные реализации Lisp не позволяют вам заменить их просто так. Помните, что ваши замещающие функции должны быть реализованы таким образом, чтобы они работали в соответствии со старыми функциями. Кроме того, старые версии могут быть каким-то образом встроены и не могут быть заменены везде.
Есть ли способ сказать defgeneric не генерировать программную ошибку и пойти дальше и заменить привязку функции?
Вы должны были бы убедиться, что замена работает, заменяя это. Функции, заменяющие код, могут использовать те функции, которые вы заменяете.
Тем не менее, реализации позволяют заменять функции CL, но это зависит от конкретной реализации. Например, LispWorks предоставляет переменные lispworks:*packages-for-warn-on-redefinition*
а также lispworks:*handle-warn-on-redefinition*
, Можно связать их или изменить их глобально.
В чем здесь мудрость и лучшая практика, пожалуйста?
Есть два подхода:
- использовать специфичные для реализации способы для замены стандартных функций Common Lisp
Это может быть опасно. Кроме того, вам нужно поддерживать его для всех реализаций CL, которые вы хотите использовать...
- используйте языковой пакет, где вы определяете свой новый язык. Здесь это будет стандартный Common Lisp плюс ваши расширения / изменения. Экспортируйте все, что будет использовать пользователь. В вашем программном обеспечении используйте этот пакет вместо
CL
,