2011-10-19 60 views
12

如何測試變量是否已被聲明或分配(即,檢查是否定義了「a」,當我期望程序調用此類代碼時(def a(create- A))?Clojure:確定是否聲明變量

及相關---如何回答這個問題涉及到解決已聲明的符號(即功能)的問題?Clojure: determine if a function exists

這似乎是一個定義的變量應可以在定義函數的同樣意義上進行檢查,但是我發現用於確定函數是否存在的解決方案不足以確定是否存在變量。

一些上下文:我正在爲多開發人員項目編寫單元測試,並且要確保已經定義了測試數據和不同類中的方法。由於沒有良好的clojure IDE支持,在我看來,鑑於其鬆散的結構,在測試其輸出/內容之前測試方法名稱和變量名稱是存在的。要做到這一點

+0

我看到'resolve'已經在你鏈接到的文章中提到過了,你能描述一下它的用途嗎? – Paul

+0

是的。我注意到了這一點,但想知道在鏈接示例中使用單個qoute還是雙重qouted方法。這與用於解析函數的(resolve(符號「my-function-isnt-a-symbol」))有何不同? – jayunit100

+1

可能重複的[如何確定符號是否有界(var定義)?](http://stackoverflow.com/questions/4908071/how-to-determine-if-symbol-is-bounded-var-defined) –

回答

12

您可以使用resolve,看是否該變量被綁定/定義:

(resolve 'meaning) 
nil 

(def meaning 42) 
#'user/meaning 

(resolve 'meaning) 
#'user/meaning 

,或者你可以布爾檢查它,如果你需要的true/false:

(boolean (resolve 'meaning)) 
true 
+0

是的,這是正確的答案:) – jayunit100

4

一種方法是使用ns-resolve,例如:

user=> (def a "hello a") 
user=> (ns-resolve *ns* 'a) 
#'user/a 
user=> (ns-resolve *ns* 'b) 
;nil     ; This assumes b hasn't been defined before... 

請注意,如果名稱空間限定的符號被選中,那麼您(在本例中*ns*以上)通過什麼作爲第一個參數不要緊:

user=> (ns-resolve 'user 'a) 
#'user/a 
user=> (ns-resolve 'other 'a) 
nil 
user=> (ns-resolve 'other 'user/a) 
#'user/a 

通過@tolitius提到的resolve功能實際上是ns-resolve的簡寫,其中namespace參數總是爲NS,這取決於用例可能更方便。

4

正如其他人所說,如果定義了一個符號,則resolve將返回符號的var,否則返回nil。此外,您可以使用bound?來檢查var是否具有綁定的值。

 
user=> (resolve 'foo) 
nil 
user=> (def foo) 
#'user/foo 
user=> (resolve 'foo) 
#'user/foo 
user=> (bound? #'foo) 
false 
user=> (def foo 5) 
#'user/foo 
user=> (bound? #'foo) 
true 
1

由於是Clojure中沒有很好的IDE支持,在我看來是, 鑑於其鬆散的結構,這是很好的測試它們的輸出/內容之前測試方法的名稱和 變量名存在。

這是堅果。你真的想要一個測試說:「糟糕!你忘了定義foobar!」而不是試圖運行foobar並看到Clojure的「無法解析符號」消息?

你從中得到什麼?你失去了堆棧跟蹤,這可能是有用的,例如,如果測試通過其他代碼傳遞了錯誤的函數名稱。更好地瞭解哪些行拼寫錯誤的foobar比搜索整個測試命名空間更好。

+0

好吧,「無法解決符號foobar」可能是因爲名稱空間未正確導入。一個導入所有名字的單元測試正確地證實了螞蟻未解析的符號實際上是由於ns導入錯誤,而不是真正缺少的資源......(最近正在研究龐大的PHP代碼庫,並發現單元測試對於具有外部依賴和多個命名空間的多開發者項目來說,變量,方法和資源是絕對的生命保護者)。 – jayunit100