gpt4 book ai didi

lisp - 如何将 “taken”单词用作CLOS泛型

转载 作者:太空宇宙 更新时间:2023-11-03 18:37:26 26 4
gpt4 key购买 nike

泛型似乎提供了一个很好的工具,可以提取一个常见的单词,并使其根据您通过的类型在事物上起作用,并且事后具有扩展性。

但是,那些已经被使用但没有被定义为通用词的普通单词呢?例如,如果我尝试定义“删除”:

(defclass reticulator () (splines))

(defmethod remove ((item reticulator)
sequence &key from-end test test-not start end count key))

我在SBCL中收到错误:

COMMON-LISP:REMOVE already names an ordinary function or a macro.



是否有一种习惯用法或认可的方法来“通用化”这些内置功能之一?人们这样做吗?

只是为了看看会发生什么,我尝试使用通用替代REMOVE:
(defgeneric remove (item sequence &key from-end test test-not start end count key))

WARNING: redefining COMMON-LISP:REMOVE in DEFGENERIC



我不知道是否有一种“好的”方式来做到这一点,它将以旧的实现方式传递给旧的实现,并允许对想要赋予单词新含义的特定类型进行重载。

最佳答案

事情为什么如此?

Common Lisp的第一个版本是从1981/82年开始设计的,其结果在1984年出版了《 Common Lisp the Language》一书。该语言本身主要是基于Lisp Machine Lisp(又名Zetalisp)设计的。 Zetalisp比当时发布的Common Lisp大得多,并且包含一个称为Flavors的早期对象系统。 Zetalisp中的许多内容都是以面向对象的方式实现的-确实提高了性能,而在Lisp Machines上,性能的影响并不那么大-但是他们拥有专门的处理器,这些处理器对指令集进行了优化。因此,Common Lisp不包含任何对象系统,因此针对当时典型处理器的性能进行了稍微优化。在更高版本的Common Lisp中,将添加一个对象系统-当有足够的关于Lisp的面向对象扩展的经验时-请记住,我们谈论的是80年代初期。

1984年的Common Lisp具有有限形式的通用行为。例如,REMOVE函数可用于序列-序列是一种新类型,具有向量和列表作为子类型。

后来,Common Lisp于1986年开始标准化,其中一个正在寻找Common Lisp的对象系统-所提出的建议都不够好-因此,在New Flavors的基础上开发了一个新的系统(来自Symbolics,是上述版本的较新版本) flavor )和通用循环(来自Xerox PARC)。那些已经具有通用功能,但是只有一次调度。然后,CLOS添加了多个调度。

决定不使用CLOS泛型函数替换基本功能-原因之一是性能:CLOS泛型函数需要相对复杂的分派(dispatch)机制,并且此分派(dispatch)是在运行时确定的。没有CLOS功能具有静态编译时分派(dispatch)功能,也没有标准化功能可将类的各个部分“封闭”->从而使它们无法更改。因此,像CLOS这样的高动态系统具有运行时成本。

一些函数被定义为CLOS通用函数(例如PRINT-OBJECT),而一些实现则具有Common Lisp和CLOS实现的大部分(流,条件等)-但这是实现特定的,不是标准要求的。还有几个库,它们提供内置CL功能的基于CLOS的功能:例如具有可扩展的基于CLOS的流的I/O。

另请注意,重新定义现有的Common Lisp函数是未定义的行为。

因此,Common Lisp选择提供一个功能强大的对象系统,但将其留给各个实现使用基本语言的CLOS的具体数量–局限性在于通常不应将标准化为普通非CLOS泛型函数的功能由用户替换为CLOS功能。

一些Lisp方言/实现试图处理这些问题,并试图定义一个更快的CLOS变体,然后这将成为许多语言的基础。例如,参见Apple的Dylan语言。有关一些较新的方法,请参见语言Julia。

您自己改进的Common Lisp

包(->符号 namespace )允许您定义自己的改进的CL:在这里,我们定义了一个新的包,其中包含所有CL符号,只有cl:remove被其自己的符号遮盖。然后,我们定义一个名为bettercl::remove的CLOS泛型函数,并编写两个示例方法。

CL-USER 165 > (defpackage "BETTERCL" (:use "CL") (:shadow cl:remove))
#<The BETTERCL package, 1/16 internal, 0/16 external>

CL-USER 166 > (in-package "BETTERCL")
#<The BETTERCL package, 1/16 internal, 0/16 external>

BETTERCL 167 > (defgeneric remove (item whatever))
#<STANDARD-GENERIC-FUNCTION REMOVE 4060000C64>

BETTERCL 168 > (defmethod remove (item (v vector)) (cl:remove item v))
#<STANDARD-METHOD REMOVE NIL (T VECTOR) 40200AB12B>

BETTERCL 169 > (remove 'a #(1 2 3 a b c))
#(1 2 3 B C)

BETTERCL 170 > (defmethod remove ((digit integer) (n integer))
"remove a digit from an integer, returns a new integer"
(let ((s (map 'string
(lambda (item)
(character (princ-to-string item)))
(cl:remove digit
(map 'vector
#'digit-char-p
(princ-to-string n))))))
(if (= (length s) 0) 0 (read-from-string s))))
#<STANDARD-METHOD REMOVE NIL (INTEGER INTEGER) 40200013C3>

BETTERCL 171 > (remove 8 111888111348111)
11111134111

现在,您还可以从 BETTERCL导出符号,以便可以在应用程序包中使用此包,而不是 CL包。

以前已经使用过这种方法。例如,CLIM(Common Lisp接口(interface)管理器)定义了一个包 CLIM-LISP,它用作进行编程的方言。

Common Lisp有时提供功能和相关的CLOS通用功能

请参阅标准函数 DESCRIBE,可以通过为标准CLOS泛型函数 DESCRIBE-OBJECT编写方法来扩展它。

常见Lisp的改进实验

使标准Common Lisp功能可扩展的另一种方法是,将其替换为版本,然后再使用基于CLOS的可扩展协议(protocol)。注意,如何替换标准功能是特定于实现的,并且效果也可能是特定于实现的。例如,如果编译器已将内置函数内联到代码中,则重新定义将不会对已内联的代码产生影响。

有关这种方法的示例,请参见Christophe Rhodes的论文(PDF) User-extensible sequences in Common Lisp

何时使用通用函数?

有几件事要牢记:

当存在多个与 相关的方法时,
  • 定义CLOS泛型函数,最好是受益于通用的扩展机制,并且可能会扩展
  • 考虑性能命中
  • 对于具有相似arglist甚至相同名称但对于非常不同的域
  • 起作用的函数,不要使用单个CLOS泛型函数

    这意味着您不应在单个CLOS通用函数中定义函数,例如:
    ; do some astrophysics calculations
    (defmethod rotate-around ((s star) (u galaxy)) ...)

    ; do some computation with graphics objects
    (defmethod rotate-around (shape (a axis)) ...)

    例如,编写 :before:around:after方法可能不会产生有用的结果。

    一个可以具有两个不同的 rotate-around泛型函数,一个在 ASTRO-PHYSICS包中,另一个在 GRAPHICS-OBJECTS包中。因此,这些方法将不在同一CLOS通用函数中,并且扩展这些方法可能会更容易。

    关于lisp - 如何将 “taken”单词用作CLOS泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53574843/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com