4

我想将 elt、nth 和 mapcar 之类的名称与我正在原型设计的新数据结构一起使用,但是这些名称指定了普通函数,因此我认为需要将其重新定义为通用函数。

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

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

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

请问这里被认为的智慧和最佳实践是什么?

4

2 回答 2

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

于 2016-06-28T16:54:24.027 回答
7

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

Common Lisp 在它的某些领域有一些语言层次。软件的高级部分可能需要建立在低级结构上。

它的一个目标是对一系列应用程序足够快。

当语言没有对象系统时,Common Lisp 还引入了序列的概念,即对列表和向量的抽象。CLOS 是在最初的 Common Lisp 设计之后几年出现的。

举个例子,比如平等——对于数字。

Lisp 有=

(= a b)

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

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

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

(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.
于 2016-06-28T23:13:03.247 回答