2016-06-14 12 views
1

我有在源文件中定義的命名空間的動態無功,就像這樣:如何在Leiningen用戶手冊中製作var set!-able?

(ns mystuff.log ...) 

(def ^:dynamic *logging* #{}) 

我希望能夠set!這個變種從REPL,所以在相同的源代碼文件可以看看它。在本例中,mystuff.log/log宏查看*logging*以決定是否打印給定的表達式。在REPL,(set! *logging* #{:whatever})會很方便,在會話期間多次更改其值。

我該如何獲得Leiningen的REPL來允許這個?默認情況下,set! ing這樣的var會產生IllegalStateException,因爲set!不能更改var的根綁定。 var必須是線程局部的,可以通過set!更改。

有沒有辦法告訴Leiningen把它的REPL包裝成這樣,爲var創建一個線程局部綁定?

(binding [mystuff.log/*logging* mystuff.log/*logging*] 
    (the-leiningen-repl ...)) 

:repl-options:init選項,簡要地說明here,好像它提供了接近。顯然,REPL調用:init,這將使爲已經鍵入到REPL中的表達式建立一個線程本地綁定爲時已晚。

回答

2

您可能想要alter-var-root而不是set!。由於沒有特殊的設置或修改的REPL,這裏是你可以做什麼:

user> (def logging #{}) 
#'user/logging 

user> (alter-var-root #'logging conj :my-new-logger) 
#{:my-new-logger} 

user> (alter-var-root #'logging conj :another-new-logger) 
#{:my-new-logger :another-new-logger} 

user> logging 
#{:my-new-logger :another-new-logger} 


#{:my-new-logger :another-new-logger} 

set!只修改一個變種的當前線程綁定。 alter-var-root修改VAR的根結合:那橫跨在那裏它不是由每個線程的結合覆蓋所有線程共享的價值*


*順便說一句,這就是爲什麼alter-var-root沒有一個感嘆號。它遵循與修改根綁定的其他表單相同的約定,如def

+0

那麼,如何設置Leiningen REPL以便var在'user =>'提示符出現之前獲得線程本地綁定?換句話說,REPL應該像包裝在'binding'中一樣運行。 –

+0

讓我們退一步,問你想做什麼。 'set!'極少是改變根值的答案。大多數人都希望alter-var-root不需要這些,只需在var中設置值即可。 –

+0

我只是想能夠從REPL隨意更改自定義全局變量的值,可能多次。 (這個問題舉了一個例子:把一組東西改爲日誌。) –