我想用elt、nth和mapcar这样的名字来表示我正在创建原型的新数据结构,但是这些名字指定的是普通函数,因此我认为需要将它们重新定义为泛型函数。
重新定义这些名字可能是不好的形式?
是否有一种方法可以告诉defgeneric不生成程序错误并继续替换函数绑定?
这些不是泛型函数或只是历史函数是否有很好的理由?
这里的智慧和最佳实践是什么?
如果您正在使用SBCL或ABCL,并且不关心ANSI遵从性,您可以研究可扩展序列:
http://www.sbcl.org/manual/Extensible-Sequences
http://www.doc.gold.ac.uk/mas01cr/论文/ilc2007/序列- 20070301. - pdf
…您不能在COMMON-LISP包中重新定义函数,但是您可以创建一个新包并对您想要重新定义的函数的导入进行隐藏。
这些不是泛型函数或只是历史函数是否有很好的理由?
Common Lisp在它的某些领域有一些语言层次。软件的高级部分可能需要在低级构造上构建。
它的目标之一是足够快,以满足各种应用。
Common Lisp还引入了序列的概念,这是对列表和向量的抽象,当时该语言还没有对象系统。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这样的编程语言中尝试过了。
重新定义这些名字可能是不好的形式?
普通的Lisp实现不允许你这样替换它们。请注意,您的替换函数应该以与旧函数一致的方式实现。此外,旧版本可能会以某种方式内联,而不是到处都可以替换。
是否有一种方法可以告诉defgeneric不生成程序错误并继续替换函数绑定?
在更换时,您需要确保更换的部件正在工作。替换函数的代码,可能会使用你要替换的函数。
实现仍然允许您替换CL函数——但这是特定于实现的。例如,LispWorks提供了变量lispworks:*packages-for-warn-on-redefinition*
和lispworks:*handle-warn-on-redefinition*
。您可以绑定它们或全局更改它们。
这里的智慧和最佳实践是什么?
有两个方法:
- 使用特定的实现方式来替换标准的Common Lisp函数
这可能很危险。此外,您需要支持所有您想要使用的CL实现…
- 使用语言包,在其中定义新语言。这里,这将是标准的Common Lisp加上您的扩展/更改。导出用户将使用的所有内容。在您的软件中使用此包代替
CL
。