2011-10-07 52 views
9

我編碼的東西像REPL服務器。來自用戶的請求評估中這樣的功能:clojure - 在不同命名空間的eval代碼

(defn execute [request] 
    (str (try 
      (eval (read-string request)) 
     (catch Exception e (.getLocalizedMessage e))))) 

在單獨的線程中的每個客戶端。但他們有相同的命名空間。我如何在動態創建的命名空間中運行代碼?所以當新的客戶端連接時,我想創建新的命名空間並在那裏運行客戶端處理循環代碼。或者也許可以在其他命名空間運行(eval ..)

謝謝。

upd。
解決!

執行功能:

(defn execute 
    "evaluates s-forms" 
    ([request] (execute request *ns*)) 
    ([request user-ns] 
    (str 
     (try 
     (binding [*ns* user-ns] (eval (read-string request))) 
     (catch Exception e (.getLocalizedMessage e)))))) 

每個客戶端獲得它通過自己的命名空間:

(defn generate-ns 
    "generates ns for client connection" 
    [] (let [user-ns (create-ns (symbol (str "client-" (Math/abs (.nextInt random)))))] 
    (execute (str "(clojure.core/refer 'clojure.core)") user-ns) 
    user-ns))` 

(defn delete-ns 
    "deletes ns after client disconnected" 
    [user-ns] (remove-ns (symbol (ns-name user-ns)))) 

offtop:如何使偏移的代碼片斷開始上線的?

+1

如果您的問題已被某人的答案解決,請將該答案標記爲正確。如果您自己想出了這個答案,請在答案部分(不是問題的一部分)將答案寫下來,並將其標記爲正確。關於代碼塊的格式,只需將它們作爲單獨的段落縮進四個空格(我編輯了您的問題以修復格式)。歡迎來到Stackoverflow! –

+0

官方政策是你應該在這種情況下發布你的問題的答案。但是,有些人不喜歡這種做法,並且OP會減少答案。因此,正式的正確行動是有風險的。 – Mars

回答

15

解決:

(binding [*ns* user-ns] (eval (read-string request))) 
1

更改命名空間意味着你將不得不重新初始化所有的別名,或參閱甚至clojure.core的東西用一個完全合格的名稱:

user=> (defn alien-eval [ns str] 
     (let [cur *ns*] 
      (try ; needed to prevent failures in the eval code from skipping ns rollback 
      (in-ns ns) 
      (eval (read-string str)) 
      (finally 
       (in-ns (ns-name cur)) 
       (remove-ns ns))))) ; cleanup, skip if you reuse the alien ns 
#'user/alien-eval 
user=> (alien-eval 'alien "(clojure.core/println clojure.core/*ns*)") ; note the FQN 
#<Namespace alien> ; the effect of println 
nil    ; the return value of alien-eval 
+0

它在REPL中起作用,但它在運行時不起作用:'不能使用set'更改/建立* ns *的根綁定。 –

0

你可以寫一個宏模仿

(defmacro my-eval [s] `~(read-string s)) 

它更好地工作,因爲符號s的解析發生在調用my-eval的上下文中。感謝@Matthias Benkard的澄清。

1

(符號(STR 「客戶機」(數學/ ABS(.nextInt隨機)))

我只是想補充一點,這可能是與

(gensym "client-") 

實現(我想評論,但它變成我們不能:))