我想使用elt,nth和mapcar之类的名称来创建一个我正在进行原型设计的新数据结构,但这些名称指定普通函数,因此我认为需要重新定义为泛型函数。
大概重新定义这些名字是不好的形式?
有没有办法告诉defgeneric不要生成程序错误并继续替换函数绑定?
这些不是通用功能还是历史性的,有充分的理由吗?
这里考虑的智慧和最佳做法是什么?
答案 0 :(得分: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包中重新定义函数,但您可以创建一个新包并隐藏要重新定义的函数的导入。
答案 1 :(得分:7)
这些不是通用功能还是历史性的,有充分的理由吗?
Common Lisp在其某些领域有一些语言层次。软件的更高级别部分可能需要构建在较低级别的构造上。
其目标之一是为一系列应用程序提供足够快的速度。
Common Lisp还引入了 sequences 的概念,即列表和向量的抽象,当时语言没有对象系统。 CLOS来自最初的Common Lisp设计几年后。
以数字等等为例。
Lisp有=
:
(= a b)
这是比较数字的最快方式。 =
也仅针对数字定义。
然后有eql
,equal
和equalp
。这些工作适用于数字,但也适用于其他一些数据类型。
现在,如果您需要更高的速度,可以声明类型并告诉编译器生成更快的代码:
(locally
(declare (fixnum a b)
(optimize (speed 3) (safety 0)))
(= a b))
那么,为什么=
不是CLOS泛型函数?
a)当CLOS不存在时引入它
同样重要:
b)在Common Lisp中,对于典型的使用场景,如何将CLOS泛型函数=
与非泛型函数一样快速地知道(并且它仍然不是) - 同时保留动态类型和可扩展性
CLOS泛型函数只是速度惩罚。运行时调度成本。
CLOS最适合用于更高级别的代码,然后真正受益于可扩展性,多分派,继承/组合等功能。通用函数应该用于定义的通用行为 - 而不是类似方法的集合。
通过更好的实现技术,特定于实现的语言增强等,可以增加可以使用CLOS以高性能方式编写的代码范围。已经尝试过像Dylan和Julia这样的编程语言。
重新定义这些名字可能是一种不好的形式?
Common Lisp实现不允许您替换它们。请注意,您的替换功能应以与旧功能一致的方式实施。此外,旧版本可能以某种方式内联,并且无法在任何地方进行替换。
有没有办法告诉defgeneric不要生成程序错误并继续替换函数绑定?
您需要确保在更换时更换正常。代码替换功能可能会使用您要替换的功能。
但是,实现允许您替换CL函数 - 但这是特定于实现的。例如,LispWorks提供变量lispworks:*packages-for-warn-on-redefinition*
和lispworks:*handle-warn-on-redefinition*
。可以绑定它们或全局更改它们。
这里考虑的智慧和最佳做法是什么?
有两种方法:
这可能很危险。此外,您需要支持所有想要使用的CL实现...
CL
。