2012-02-11 37 views
6

來自Java背景,我非常喜歡靜態類型安全性,並且不知道clojure程序員如何處理數據格式定義的問題(可能不只是類型,而是一般不變量,因爲類型只是一個)clojure中的數據格式安全

這與「Clojure中的類型安全性」類似,但更關注如何在編譯時檢查類型的方面,而我更關注如何問題切實解決。

作爲一個實際的例子,我正在考慮處理特定文檔格式的編輯器應用程序。每個文檔由多種不同類型的元素組成(圖形元素,字體元素等)。不同的元素類型會有編輯器,當然也有函數用於將文檔從其字節流轉換爲字節流,磁盤格式。

我感興趣的基本問題是編輯器和讀/寫功能必須就通用數據格式達成一致。在Java中,我會將文檔的數據建模爲對象圖,例如一個類代表一個文檔,一個類代表每個元素。通過這種方式,我可以獲得關於數據結構的編譯時間保證,並且圖形元素的字段「寬度」是整數而不是浮點數。它並不保證寬度是正數 - 但是使用getter/setter接口將允許相應的類添加這樣的不變保證。

能夠依賴於此可以使處理這些數據的代碼變得更簡單,並且格式違規可以在編譯時或運行時早期(其中某些代碼試圖修改會違反不變量的數據)。

如何在Clojure中實現類似的「數據格式可靠性」?據我所知,沒有辦法執行編譯時檢查,隱藏域函數接口後面的域數據似乎不被認爲是非慣用的(或者我誤解了?),那麼Clojure開發人員應該怎麼做才能感到安全?數據的格式傳遞到它們的功能?如何讓您的代碼儘快出錯,而不是在用戶編輯了20多分鐘並嘗試保存到磁盤之後,保存功能注意到字體列表中存在由於編輯器錯誤?

請注意,我對Clojure和學習很感興趣,但沒有寫出任何實際的軟件,所以可能我只是感到困惑,答案很簡單 - 如果是這樣,對於浪費你的時間 :)。

回答

8

我沒有看到任何錯誤或unidiomatic關於使用驗證API來構建和操縱您的數據,如下所示。

(defn text-box [text height width] 
    {:pre [(string? text) (integer? height) (integer? width)]} 
    {:type 'text-box :text text :height height :width width}) 

(defn colorize [thing color] 
    {:pre [(valid-color? color)]} 
    (assoc thing :color color)) 

... (colorize (text-box "Hi!" 20 30) :green) ... 

此外,參考文獻(VARS,參考文獻,原子,藥劑)可以具有相關聯validator function可用於確保在任何時候都有效狀態。

+0

感謝迄今爲止的答案。由於這是一個相當開放的問題,我會在接受之前等一會兒。驗證函數聽起來像是一個有趣的解決方案,但是(保持這個例子),如果你有一個大文檔作爲你的狀態,每次做一個小小的改變就完全驗證它,這似乎是低效率的 - 在這樣的模型中,我猜測使用驗證操縱功能將是可取的。 – Medo42 2012-02-12 23:17:29

5

好問題 - 我還發現從靜態類型語言轉換爲動態類型語言需要更多關心類型安全性。幸運的是,TDD技術在這裏幫助了巨大的數量。

我通常會寫一個「驗證」函數來檢查所有關於數據結構的假設。我也經常用Java來做這個,因爲它不變的假設,但是在Clojure中它更重要,因爲你需要檢查類型以及類型。

然後,您可以用幾種方式驗證功能:

  • 截至REPL快速檢查:(validate foo)
  • 在單元測試:(is (validate (new-foo-from-template a b c)))
  • 對於關鍵功能的運行時檢查,例如檢查(read-foo some-foo-input-stream)有效

如果你有一個複雜的數據結構,它是多個不同組件類型的樹,你可以寫爲每個組件類型驗證功能,並具有對整個文檔調用驗證的驗證功能每個子組件遞歸地。一個很好的訣竅是使用協議或multimethods爲每個組件類型生成驗證函數多態。