2016-06-28 10 views
3

Я бы хотел использовать имена, такие как elt, nth и mapcar, с новой структурой данных, которые я прототипирую, но эти имена обозначают обычные функции, и поэтому, я думаю, переопределяться как общие функции.Замена обычной функции на общую функцию

Предположительно это плохая форма, чтобы переопределить эти имена?

Есть ли способ сказать defgeneric не генерировать программную ошибку и не выполнять привязку к функции?

Есть ли веская причина, что они не являются универсальными функциями или просто историческими?

Какая уместная мудрость и лучшая практика здесь, пожалуйста?

ответ

7

Если вы используете SBCL или ABCL, и не связаны с соблюдением ANSI, можно исследовать раздвижные последовательности:

http://www.sbcl.org/manual/#Extensible-Sequences

http://www.doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf

... вы не можете переопределять функции в пакете COMMON-LISP, но вы можете создать новый пакет и затенять импорт функций, которые вы хотите переопределить.

6

Есть ли веская причина, что они не являются универсальными функциями или просто историческими?

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 generic просто имеет ограничение скорости. Расходы на отправку.

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

С лучшей технологией внедрения, языковыми улучшениями, специфичными для реализации, и т. Д., Возможно, будет возможно расширить диапазон кода, который может быть записан с использованием CLOS. Это было опробовано с такими языками программирования, как Дилан и Джулия.

Предположительно это плохая форма, чтобы переопределить эти имена?

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

Есть ли способ сказать defgeneric не генерировать программную ошибку и не выполнять привязку к функции?

Вам необходимо убедиться, что замена работает при ее замене. Функции замены кода могут использовать те функции, которые вы заменяете.

Тем не менее, реализации позволяют заменять функции CL, но это конкретная реализация. Например, LispWorks предоставляет переменные lispworks:*packages-for-warn-on-redefinition* и lispworks:*handle-warn-on-redefinition*. Их можно связать или изменить на глобальном уровне.

Какая уместная мудрость и лучшая практика здесь, пожалуйста?

Есть два подхода:

  • реализации использование конкретных способов заменить стандартный Common Lisp функций

Это может быть опасно. Кроме того, вам необходимо поддерживать его для всех реализаций CL, которые вы хотите использовать ...

  • используйте языковой пакет, в котором вы определяете свой новый язык. Здесь это будет стандартный Common Lisp плюс ваши расширения/изменения. Экспортируйте все, что пользователь будет использовать. В вашем программном обеспечении используйте этот пакет вместо CL.

 Смежные вопросы

  • Нет связанных вопросов^_^