用通用函数替换普通函数
Replacing an ordinary function with a generic function
我想将 elt、nth 和 mapcar 等名称用于我正在制作原型的新数据结构,但这些名称指定普通函数,因此我认为需要将其重新定义为通用函数。
大概是重新定义这些名称的形式不好?
有没有办法告诉 defgeneric 不要生成程序错误并继续替换函数绑定?
这些不是通用函数或只是历史性函数是否有充分的理由?
请问这里的智慧和最佳实践是什么?
如果您使用的是 SBCL 或 ABCL,并且不关心 ANSI 合规性,则可以研究可扩展序列:
http://www.sbcl.org/manual/#Extensible-Sequences
http://www.doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf
...您不能在 COMMON-LISP 包中重新定义函数,但您可以创建一个新包并隐藏要重新定义的函数的导入。
Is there a good reason for these not being generic functions or is just historic?
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 最适用于更高级别的代码,然后真正受益于可扩展性、多调度等功能,inheritance/combinations。通用函数应该用于定义的通用行为——而不是类似方法的集合。
有了更好的实现技术、特定于实现的语言增强等,可能会增加可以使用 CLOS 以高性能方式编写的代码范围。这已经用 Dylan 和 Julia 等编程语言进行了尝试。
Presumably it's bad form to redefine these names?
Common Lisp 实现不允许您就这样替换它们。请注意,您的替换功能应该以与旧功能一致的方式实现。此外,可以以某种方式内联旧版本,而不是在任何地方都可以替换。
Is there a way to tell defgeneric not to generate a program error and to go ahead and replace the function binding?
您需要在更换时确保更换件正常工作。替换函数的代码,可能会使用您正在替换的那些函数。
仍然,实现允许您替换 CL 函数 - 但这是特定于实现的。例如 LispWorks 提供变量 lispworks:*packages-for-warn-on-redefinition*
和 lispworks:*handle-warn-on-redefinition*
。可以绑定它们或全局更改它们。
What's the considered wisdom and best practice here please?
有两种方法:
- 使用特定于实现的方式来替换标准的 Common Lisp 函数
这可能很危险。另外,您需要为要使用的所有 CL 实现支持它...
- 使用语言包,您可以在其中定义新语言。在这里,这将是标准的 Common Lisp 加上你的 extensions/changes。导出用户将使用的所有内容。在您的软件中使用此包而不是
CL
.
我想将 elt、nth 和 mapcar 等名称用于我正在制作原型的新数据结构,但这些名称指定普通函数,因此我认为需要将其重新定义为通用函数。
大概是重新定义这些名称的形式不好?
有没有办法告诉 defgeneric 不要生成程序错误并继续替换函数绑定?
这些不是通用函数或只是历史性函数是否有充分的理由?
请问这里的智慧和最佳实践是什么?
如果您使用的是 SBCL 或 ABCL,并且不关心 ANSI 合规性,则可以研究可扩展序列:
http://www.sbcl.org/manual/#Extensible-Sequences
http://www.doc.gold.ac.uk/~mas01cr/papers/ilc2007/sequences-20070301.pdf
...您不能在 COMMON-LISP 包中重新定义函数,但您可以创建一个新包并隐藏要重新定义的函数的导入。
Is there a good reason for these not being generic functions or is just historic?
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 最适用于更高级别的代码,然后真正受益于可扩展性、多调度等功能,inheritance/combinations。通用函数应该用于定义的通用行为——而不是类似方法的集合。
有了更好的实现技术、特定于实现的语言增强等,可能会增加可以使用 CLOS 以高性能方式编写的代码范围。这已经用 Dylan 和 Julia 等编程语言进行了尝试。
Presumably it's bad form to redefine these names?
Common Lisp 实现不允许您就这样替换它们。请注意,您的替换功能应该以与旧功能一致的方式实现。此外,可以以某种方式内联旧版本,而不是在任何地方都可以替换。
Is there a way to tell defgeneric not to generate a program error and to go ahead and replace the function binding?
您需要在更换时确保更换件正常工作。替换函数的代码,可能会使用您正在替换的那些函数。
仍然,实现允许您替换 CL 函数 - 但这是特定于实现的。例如 LispWorks 提供变量 lispworks:*packages-for-warn-on-redefinition*
和 lispworks:*handle-warn-on-redefinition*
。可以绑定它们或全局更改它们。
What's the considered wisdom and best practice here please?
有两种方法:
- 使用特定于实现的方式来替换标准的 Common Lisp 函数
这可能很危险。另外,您需要为要使用的所有 CL 实现支持它...
- 使用语言包,您可以在其中定义新语言。在这里,这将是标准的 Common Lisp 加上你的 extensions/changes。导出用户将使用的所有内容。在您的软件中使用此包而不是
CL
.