使用类的通用Lisp替代方案



我想知道如何存储单个变量并对该变量具有特定的函数。我想知道是否有创建类的替代方案。

具体来说,我正在创建一个应用程序,在这个应用程序中,我存储一个时间值,该值表示从基本时间(例如,Jan 1, 2000, 00:00:00)经过的秒数。我想对这个值执行一些操作,比如将秒值转换为特定的时间或日期,或者将日期转换为特定的秒值。

我已经使用一个类完成了这个,但是它看起来很浪费。具体来说,每次访问经过秒数的存储值时,它看起来类似于(time-time time),其中time-time是时间实例time的访问器。

有没有更好的方法来设计这个,也许不需要类?

访问器名称

您可以在CLOS中以任何您喜欢的方式命名访问器。访问器函数可以称为seconds:

CL-USER 23 > (defclass mytime ()
               ((seconds :accessor seconds :initarg :seconds)))
#<STANDARD-CLASS MYTIME 422015CDD3>
CL-USER 24 > (let ((mt (make-instance 'mytime :seconds 100)))
               (values (seconds mt)
                       (truncate (seconds mt) 60)))
100
1

通过accessor函数更短地访问slot

Common Lisp也有一个形式WITH-ACCESSORS。它允许我们在代码中使用符号而不是访问器形式——对于某个CLOS对象。在下面的示例中,我们可以使用secs,它在代码中看起来像一个变量,但是Common Lisp将确保它实际上调用了访问器seconds。我们可以写secs而不是(seconds mt)。因此,它有助于使封闭的代码更短。将下一个示例与上面的代码进行比较。

CL-USER 25 > (let ((mt (make-instance 'mytime :seconds 200)))
               (with-accessors ((secs seconds))
                   mt
                 (values secs (truncate secs 60))))
200
3

SLOT-VALUE

CLOS也有WITH-SLOTS用于通过插槽名称访问插槽,这里mytime实例的seconds插槽可以通过名称secs访问:

CL-USER 26 > (let ((mt (make-instance 'mytime :seconds 200)))
               (with-slots ((secs seconds))
                   mt
                 (values secs (truncate secs 60))))
200
3

如果你有一个类,它只是包装一个对象,并且该对象有一个已知的类型,那么你总是可以为该对象的类编写方法:

(defmethod time-as-unix-time ((tm integer))
  (- tm (load-time-value (encode-universal-time 0 0 0 1 1 1970 0))))
例如

当然,如果面向对象的狂热者发现你在做这种事情,他们会把你扔进一个充满钉子的坑里:毫无疑问,这违反了封装或其他一些邪教规则。

您可以在词法范围内尝试闭包,如下所示:

(let ((time (get-universal-time)))
  (defun set-time(tm)
    (setf time tm))
  (defun get-time()
    time)
  (defun get-time-in-some-other-format()
    ;; calculate return value based on 'time'
    )
)

相关内容

  • 没有找到相关文章

最新更新