2012-01-13 22 views
1

嗨,大家好:在java中,我們都有使用我們的ide來遍歷複雜數據類型深度的經驗:Clojure:地圖列表地圖...如何討論任何數據結構

dog.getCollar().getCollarTag().getName(); 

但是,在Clojure中,由於缺少靜態類型,這變得不重要。我們如何「抵抗」或者對抗可能來自嵌套數據結構的複雜事物的Clojure?

1)對clojure數據結構的深度有一個可取的「限制」?

2),用於處理abritrarily深度嵌套的數據結構的一個常見成語,這防止 錯誤,例如誤的列表在地圖,或無法正確下部/上部外殼一個變量名?

原諒我,如果我在這裏聽起來有點偏離範式......可能是這樣的錯誤可以通過在REPL中不斷測試來有效抑制..但是,我想知道是否還有其他方法爲確保在編譯時,該代碼儘可能正確的(即單元測試,IDE/emacs的插件,等...)

回答

5

關鍵字是你的朋友在這裏

(def my-animals { :dog {:collar {:tag {:name "fido"}}}}) 

嘗試堅持與地圖,因爲他們更內在自我描述。
然後用螺紋先玩和.. macroes

(-> my-animals :dog :collar :tag :name) 

,走的事實,關鍵字也是看起來他們的自我起來的地圖功能的優勢。

當您在帶有代碼完成的IDE中工作時,它將解析代碼,然後構建有關該代碼的數據,然後解析該數據以生成其建議。如果你的數據是自我聲明的(它可以是'讀'),那麼即使沒有IDE,你也可以得到這個數據。

PS:這導致約「代碼數據」已經被人過多次表示更聰明,比我:)

2

測試在REPL你功能的正確性是一個良好的開端標準咆哮。一個改進的好方法是單元測試,也許可以使用前置和後置條件(http://objectcommando.com/blog/2010/03/07/design-by-contract-with-clojure/)。

使用關鍵字時,您的示例可以變成(get-in dog [:collar :tag :name])。和「修改」assoc-inupdate-in

+0

好的答案,最近我在一個項目上做了同樣的工作。 REPEL節省時間,進入,更新,關聯對於嵌套地圖非常有用,解構和多方法可以消除混亂,並有助於專注於處理數據的邏輯。對於驗證,我已經使用closchema https://github.com/jestan/closchema,它大部分時間都在工作:) – 2012-01-16 15:50:24

1

鏈式獲得者往往違反了Law of Demeter。在這樣做時,您將代碼耦合到整個數據結構,這可能會非常棘手和複雜。在函數式語言中,clojure更自然地使用遞歸和序列處理來保持簡單和習慣。所以:

  1. 告訴,別問。而不是要求「狗的領子的標籤的名稱......」嘗試詢問狗對象或高級功能來做你想做的事。
  2. 正如ponzao所說,測試,測試和測試。在REPL測試瀏覽您的選項,寫小單元測試爲
+0

我從來沒有聽說過德米特法律適用於函數式語言或數據結構。 – 2012-01-14 18:48:27

+0

@DavidJacobs Demeter的*法則可以被理解爲「更喜歡更高層次的抽象概念」。*告訴別問*僅僅是面向對象的說法:「不要依賴表示;依賴於協議「。它們都適用於FP和OOP。例如,考慮一個總結列表元素的函數。你可以通過模式匹配列表的頭部和尾部來編寫它,但最好不要關心具體的類型,而應該使用'reduce'。突然你的功能在所有的集合上工作,並且當你的程序切換到其他數據結構時不會中斷。 – 2012-01-16 10:29:35

0

How do we "defend" or Clojure against complexites that might arrive from nested data structures?

你不能。這是這種語言的失敗之一。如果你想靜態輸入,那麼clojure不是你的東西。很多人會推薦使用嵌套地圖,這些地圖很慢,根本不提供安全性,也不是數據類型。地圖是一種數據類型,嵌套地圖不是,它們是假裝的對象。就像javascript一樣,clojure要求程序員跟蹤各種數據的實際內容,因爲Clojure中的數據是由5種不同的數據結構組成的,而不是數據結構本身。

1

在這方面,我發現了一個很棒的圖書館,它是製作棱鏡的人的Schema library。它提供了一種爲嵌套數據結構添加可選鍵入的方法,例如您在問題中引用的數據結構。這可以在運行時(或僅在測試時)執行,以驗證對函數的輸入。另外,它也是一個很好的文檔,描述了函數對其輸入的假設(這不是小事)。