用普通函数替换普通函数

Rob*_*ell 4 common-lisp clos generic-function

我想使用elt,nth和mapcar之类的名称来创建一个我正在进行原型设计的新数据结构,但这些名称指定了普通函数,因此,我认为需要重新定义为泛型函数.

据推测,重新定义这些名称是不好的形式?

有没有办法告诉defgeneric不生成程序错误并继续替换功能绑定?

这些不是通用功能还是历史性的,有充分的理由吗?

请问这里考虑的智慧和最佳做法是什么?

Gre*_*olz 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包中重新定义函数,但您可以创建一个新包并隐藏要重新定义的函数的导入.


Rai*_*wig 7

这些不是通用功能还是历史性的,有充分的理由吗?

Common Lisp在其某些领域有一些语言层.软件的更高级别部分可能需要构建在较低级别的构造上.

其目标之一是足以应对各种应用.

Common Lisp还在语言没有对象系统的时候引入了序列的概念,列表和向量的抽象.在最初的Common Lisp设计之后几年,CLOS问世了.

举个例如相等的东西 - 数字.

Lisp有=:

(= a b)
Run Code Online (Sandbox Code Playgroud)

这是比较数字的最快方法.=也仅为数字定义.

然后有eql,equalequalp.这些工作用于数字,但也适用于其他一些数据类型.

现在,如果您需要更快的速度,可以声明类型并告诉编译器生成更快的代码:

(locally
  (declare (fixnum a b)
           (optimize (speed 3) (safety 0)))
  (= a b))
Run Code Online (Sandbox Code Playgroud)

那么,为什么=不是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*.可以绑定它们或全局更改它们.

请问这里考虑的智慧和最佳做法是什么?

有两种方法:

  • 使用特定于实现的方法来替换标准的Common Lisp函数

这可能很危险.另外,您需要为要使用的CL的所有实现支持它...

  • 使用语言包,您可以在其中定义新语言.这将是标准的Common Lisp以及您的扩展/更改.导出用户将使用的所有内容.在您的软件中使用此包而不是CL.