用普通函数替换普通函数

时间:2016-06-28 15:23:05

标签: common-lisp clos generic-function

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

大概重新定义这些名字是不好的形式?

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

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

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

2 个答案:

答案 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)

这是比较数字的最快方式。 =也仅针对数字定义。

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

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

(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*。可以绑定它们或全局更改它们。

  

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

有两种方法:

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

这可能很危险。此外,您需要支持所有想要使用的CL实现...

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