2015-05-06 66 views
4

這實際上可能是XY-problem,所以我會試着解釋一下目標是什麼。枚舉命名空間並在ClojureScript中動態加載它們

我正在構建一個由一組Reagent組件組成的ClojureScript應用程序。它提供了一個用戶界面,您可以在其中動態添加或刪除UI元素。這些UI元素(組件)具有某種類型。例如Markdown組件is-a文本組件。無論何時向用戶提供添加文本的選項,我們都會列出所有匹配類型+ descendants的組件(在這種情況下,Markdown可能有其他組件)。

我編寫它的方式如下。 每個組件都位於其自己的名稱空間中,該名稱空間包含一個可返回新組件的構建器函數。在命名空間的根也呼籲在我們需要和枚舉所有這些組件在地圖像一些不同的命名空間(derive ::類型::母)

現在:

(ns app.components 
    (:require 
    [app.gui.markdown :as markdown] 
    [app.gui.study-list :as study-list])) 

(def all 
    {markdown/t markdown/builder 
    study-list/t study-list/builder}) 

/t指的是用於定義層次結構的命名空間限定關鍵字。我們使用all地圖來提供面向用戶的菜單的數據(可以添加哪些組件,按類型進行過濾)。

現在,你可以想象,這不是很漂亮。因爲它現在必須手動維護層次結構中所有類型的(可能)長列表。

相反,我會做類似(def all (components-of (descendants ::root)))的東西,但我不確定如何解決這個問題,因爲我認爲它需要按名稱查找變量(在ClojureScript中不支持)。

所以我的問題是:你如何維護ClojureScript中的地圖或名稱空間+動態變量列表?

+1

也許一個宏會有幫助嗎?或與.cljc的詭計? –

回答

3

你不能動態地做到這一點,但據我可以告訴你的問題沒有太大的需要。 ClojureScript宏可以反映回編譯器 - 你可以很容易地使用cljs.analyzer.api命名空間來找出你需要的變量(通過var元數據或其他),並自動發出你想要的運行時信息映射。這實際上與cljs.test/run-tests的工作方式非常相似。它使用編譯器過濾掉所有名稱空間中的所有變量,並附上:test元數據,並生成用於測試每個變量的代碼。這是值得詳細檢查cljs.test看看如何做到這一點。

+0

謝謝,這是非常有益的!看起來我可以從cljs.test中提取相關位。我沒有完全意識到clj和cljs之間的宏互操作。 – JoelKuiper