2014-05-24 70 views
6

如何在Clojure數據結構中標記節點?

  • 一個Clojure的數據結構,我們稱之爲dom,向量的樹和無限期深度 地圖;
  • 其中一個特定的節點,我們稱之爲focus節點,簡稱爲 進入樹的路徑:一系列密鑰,例如你可以提供給 get-in

我會在一個函數的聚焦點上決定,我想以某種方式代表可以傳遞給另一個函數在不違反不變性,是不是在某種程度上的方式聚焦節點的這種選擇與Clojure持久的數據結構衝突。

當我遍歷樹,我想不同的方式對待focus節點:例如,如果我打印的樹,我可能要打印focus節點大膽

如果我使用C或Java,我可以保存指向/ focus節點的指針/引用,我可以在遍歷樹時與當前節點進行比較。我不認爲這是做Clojure中以正確的方式:感覺哈克,我敢肯定有一些方法來做到這一點,它利用Clojure的持久數據結構。

該解決方案必須在Clojure和ClojureScript中工作。

我能想到的選項是:

  1. 存儲參考並覈對。
  2. 將標記附加到相關節點。
  3. 同時遞歸到樹中並沿着標記節點的路徑。

    • 選項(1)沒有吸引力,正如我已經解釋過的。
    • 選項(2)似乎是最好的,並給予持久的數據結構無痛苦。
    • 選項(3)與選項(2)類似,不同之處在於它將標記和遍歷步驟組合在一起。

我確定這是一個常見問題。有沒有標準的解決方案?

+0

我想你可以使用元數據來實現2,但我不知道一個通​​用的解決方案 –

+0

謝謝。我可以使用元數據,但可能不會。這個問題比實施更廣泛一些。 – Joe

+0

重新閱讀這篇文章絕對不會讓人感到痛苦,但我不認爲我在問一個主要基於意見的問題。完全有可能(並且我無法知道)有這樣做的標準慣用模式。如果答案是「否」,那麼這是一個有效的答案。 – Joe

回答

2

我建議你重新考慮@ MerceloMorales的建議:使用元數據。您的節點對象應具有不影響其正常功能的意外屬性。這就是元數據的設計目的。它在ClojureScript中有效。我能想到使用元數據的唯一原因是,節點值不是Clojure的對象,但是,例如,一個數字。

The Clojure Cookbook, 2.22. Keeping Multiple Values for a Key,盧克Vanderhart使用元數據來解決類似的問題:標記需要被解釋爲集合而不是單個值的條目。

另一種方法可能是使用拉鍊遍歷/修改節點樹。根據 - 你猜對了 - 元數據來實現拉鍊。

我分享你對元數據的疑慮:它只是將任何舊的東西附加到你的數據感覺不安 - 比如感染寄生蟲。然而,它就像任何其他物體一樣是不變的物體的一部分。


使用拉鍊的建議是天真:本standard clojure zippers是專爲順序容器,而不是聯想的人的層次結構。

+0

感謝您的回答。也許我不清楚我對元數據的看法:使用它沒有問題,但使用元數據或其他方法存儲「標記」並不重要。我只是在問一個關於這種方法的更一般的問題。 – Joe

+0

我覺得我一直在努力溝通我的問題,也許不應該舉一個例子。我只想根據路徑在樹中指定一個特定節點,以便另一個功能可以識別節點。我會看看我是否可以編輯問題以使其更清晰。 – Joe

+0

@Joe很好,把:)。不過,例子有所幫助。 – Thumbnail

1

請參閱Brandon Bloom的Dendrology talk以獲得關於此類問題的一些很好的概述。

我相信「標記」或以其他方式更新樹狀結構化數據的方便性在於他強烈建議始終將節點表示爲嵌套地圖而不是矢量(或矢量和地圖的混合物)。基於通過按鍵的矢量描述路徑上的標記是如此的簡單:

(update-in tree-data path assoc :is-focussed true) 

你的原始數據結構將保持不變,除了升級的節點通過更新在股一切結構返回的新的與原現在可以在遍歷時輕鬆測試:is-focussed屬性。