2011-10-07 35 views
9

Tôi đang mã hóa một cái gì đó như REPL Server. Yêu cầu từ người dùng đánh giá ở chức năng như vậy:clojure - mã eval trong không gian tên khác nhau

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

Mỗi khách hàng trong chuỗi riêng biệt. Nhưng chúng có cùng một không gian tên. Làm thế nào tôi có thể chạy mã trong không gian tên được tạo động? Vì vậy, khi khách hàng mới được kết nối, tôi muốn tạo không gian tên mới và chạy mã vòng lặp xử lý khách hàng tại đó. Hoặc có thể chạy (eval ..) trong không gian tên khác?

Cảm ơn.

cập nhật.
Giải quyết!

Execute chức năng:

(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)))))) 

Mỗi khách hàng được nó là không gian tên riêng theo:

(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: Làm thế nào để làm cho offsets trong đoạn mã trên bắt đầu của dòng?

+1

Nếu vấn đề của bạn được giải quyết bởi câu trả lời của ai đó, vui lòng đánh dấu câu trả lời là chính xác. Nếu bạn tự mình đưa ra câu trả lời này, vui lòng viết câu trả lời trong phần câu trả lời (không phải là một phần của câu hỏi) và đánh dấu câu trả lời đúng. Về định dạng các khối mã, chỉ cần viết chúng như các đoạn riêng biệt thụt vào bởi bốn dấu cách (tôi đã chỉnh sửa câu hỏi của bạn để sửa định dạng). Chào mừng bạn đến với Stackoverflow! –

+0

Chính sách chính thức là bạn nên đăng câu trả lời cho câu hỏi của mình trong tình huống này. Tuy nhiên, một số người không thích thực hành đó, và câu trả lời downvote bởi OP. Vì vậy, hành động chính xác chính xác là nguy hiểm. – Mars

Trả lời

15

quyết:

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

Thay đổi không gian tên có nghĩa là bạn sẽ phải khởi tạo lại tất cả các bí danh, hoặc tham khảo thậm chí clojure.core thứ với một tên đầy đủ:

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

nó hoạt động trong REPL, nhưng nó không hoạt động trong thời gian chạy: 'Không thể thay đổi/thiết lập ràng buộc gốc của: * ns * với tập hợp' –

0

Bạn có thể viết một macro bắt chước

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

Nó hoạt động tốt hơn khi đánh dấu vì biểu tượng độ phân giải của s xảy ra trong ngữ cảnh gọi là my-eval. Cảm ơn @Matthias Benkard đã giải thích rõ.

1

(biểu tượng (str "khách hàng-" (Math/abs (.nextInt ngẫu nhiên)))

Tôi chỉ muốn thêm, rằng điều này có thể đạt được với

(gensym "client-") 

(Tôi muốn bình luận, nhưng nó quay của chúng tôi mà tôi không thể :))

Các vấn đề liên quan