【问题标题】:If generic functions work well alone, what is the value of defclass?如果泛型函数单独运行良好,defclass 的价值是什么?
【发布时间】:2023-02-07 20:44:40
【问题描述】:

我读了很多关于 CL 中的泛型函数的文章。我得到它。我明白为什么它们很有价值。

主要是,当我想用​​不同的数据类型执行类似的操作时,我会使用它们,如下所示:


(defgeneric build-url (account-key)
  (:documentation "Create hunter api urls"))

(defmethod build-url ((key number))
  "Build lead api url"
  (do-something...))

(defmethod build-url ((key string))
  "build campaign api url"
  (do-somthing... ))

在此示例中,campaign-urllead-url 是结构 (defstruct)。

我的问题是,在较高层次上,类如何为通用函数 + 结构一起工作的方式增加价值?

【问题讨论】:

    标签: common-lisp sbcl clos


    【解决方案1】:

    结构比类更受限制和更“静态”:一旦定义了结构,编译器就可以生成有效访问其槽的代码,可以假定它们的布局是固定的,等等。有很多内联或宏扩展完成了当结构发生变化时,有必要从头开始重建一切。能够在运行时重新定义结构不是标准定义的东西,它只是试图变得更好的实现。

    另一方面,类具有更多特性并且在运行时更易于操作。假设你写这个类:

    (defclass person () 
      ((name :initarg :name :reader .name))) 
    

    你实例化它:

    (defparameter *someone* (make-instance 'person :name "Julia O'Caml"))
    

    现在可以更新类定义:

    (defparameter身份证计数器0) (defun 生成-id () (包括身份证计数器))

    (defclass 人 () ((名称:initarg:名称:读者.name) (dob :initarg :date-of-birth :reader .date-of-birth) (%id :reader .id :initform (generate-id))))

    现在,已经存在的*someone*有两个额外的字段,未绑定的dob和自动初始化为1的%id。关于Object Creation and Initialization (7.1)的整个部分定义了如何重新定义对象,改变类等

    而且,这个机制不是固定的,上面描述的很多步骤都依赖于泛型函数。可以定义对象的分配、初始化等方式。这个概念被标准化为Meta-Object Protocol,它还引入了元类的概念:通常一个类有一个名称、父类、槽等,但您可以向类中添加新成员,或更改实例槽的组织方式(也许您只需要一个全局句柄和一个连接,而实际槽存储在另一个进程中?)。

    最终结果是,在标准中,结构(没有 :type 选项)实际上是具有 structure-class 元类的类。它们的行为不像standard-class,因为它们受到更多限制,因此受到更积极的编译优化(通常)。

    如果您需要像在 C 中一样编程,那么结构很好,并且您可以在结构更改时重新编译所有代码。然而,在所有情况下都使用它们是不成熟的优化。现在可以使用大量标准对象而不会注意到速度太慢(有点像 Python)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-05
      • 1970-01-01
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多