2016-08-22 96 views
0

我想知道如何存儲單個變量並在該變量上具有特定功能。我想知道是否有其他方法來創建課程。Common Lisp替代使用類

具體來說,我創建了一個應用程序,在該應用程序中存儲表示從基準時間(例如2000年1月1日,00:00:00)過去的秒數的時間值。我想對此值執行操作,例如將其從幾秒鐘轉換爲特定時間或日期,或從日期轉換爲特定秒。

我已經做了這個使用類,但它看起來很浪費。具體而言,每次訪問所存儲的值所花費的秒數時間,它看起來將類似於(time-time time),其中time-time是時間實例time的訪問者。

有沒有更好的方法來設計這個,也許沒有類?

+2

爲什麼不把它作爲一個整數存儲? – jkiiski

+2

需要說明的是,您不想使用作爲標準一部分的[通用時間函數](http://www.lispworks.com/documentation/HyperSpec/Body/f_get_un.htm)? –

+0

按照頻率的順序,你用它做什麼?這是特定的時間,還是自抵消後的時間過去了? – Sylwester

回答

3

如果您有一個只包裝單個對象的類,並且該對象具有已知類型,那麼您總是可以爲該對象的類編寫方法:

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

例如,

當然,面向對象的狂熱者會讓你陷入一個充滿尖峯的坑裏,如果他們抓住你做這樣的事情:它無疑會違反封裝或邪教的其他規則。

+1

我可以使方法比不使用類的類型更具限制性嗎? – audrow

+0

@audrow嗯,你*是*使用一個類,只是一個[內置於](http://www.lispworks.com/documentation/HyperSpec/Body/t_built_.htm#built-in-class)。你可以爲任何其他類定義任何類型的「內置類」方法:你不能做的是對它進行子類化,並且它沒有任何槽或除標準之外的其他屬性爲它定義。 – tfb

+0

我明白了。謝謝。 – audrow

2

你可以嘗試封閉過這樣的詞彙範圍:

(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' 
    ) 
) 
+0

你可能希望成爲'let((time(get-universal-time)))...)'?這是一種選擇,但它也使得你只有*一個*時間結構的實例。這可能是不方便的... –

+0

對不起,現在修正了這個錯字。 –

+0

這很美。在這個例子之前,我不明白如何在詞法範圍上使用閉包。謝謝。 – audrow

5

訪問者的名字

您可以命名在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 

通過縮短存取函數

的Common Lisp也有一個形式WITH-ACCESSORS訪問插槽。它允許我們在代碼中使用符號而不是訪問者形式 - 對於某個CLOS對象。在以下示例中,我們可以使用secs,它看起來像代碼中的變量,但Common Lisp將確保它實際上調用訪問器seconds。我們可以寫secs而不是(seconds mt)。因此它有助於縮短包含的代碼。比較下面的例子和上面的代碼。

:通過 SLOT-VALUE

CLOS到插槽

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

較短的訪問也有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