2011-10-07 8 views
9

मैं आरईपीएल सर्वर की तरह कुछ कोडिंग कर रहा हूं। उपयोगकर्ताओं से अनुरोध इस तरह के फ़ंक्शन में मूल्यांकन करता है:क्लोजर - विभिन्न नामस्थान में eval कोड

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

प्रत्येक क्लाइंट अलग थ्रेड में। लेकिन उनके पास एक ही नामस्थान है। मैं डायनामिक निर्मित नेमस्पेस में कोड कैसे चला सकता हूं? तो जब नया क्लाइंट कनेक्ट होता है, तो मैं नया नेमस्पेस बनाना चाहता हूं और वहां क्लाइंट हैंडलिंग लूप कोड चलाने के लिए। या शायद अन्य नामस्थान में (eval ..) चलाने के लिए संभव है?

धन्यवाद।

अपडेट।
हल हो गया!

निष्पादित समारोह:

(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

आधिकारिक नीति यह है कि आपको इस स्थिति में अपने प्रश्न का उत्तर पोस्ट करना चाहिए। हालांकि, कुछ लोग उस अभ्यास को पसंद नहीं करते हैं, और ओपी द्वारा जवाब को कम करते हैं। तो आधिकारिक तौर पर सही कार्रवाई जोखिम भरा है। – Mars

उत्तर

15

हल:

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

बदलने नाम स्थान का मतलब है कि आप सभी उपनामों reinitialize करने के लिए है, या पूरी तरह से योग्य नाम के साथ भी 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

यह आरईपीएल में काम करता है, लेकिन यह रनटाइम में काम नहीं करता है: 'रूट बाध्यकारी को बदल/स्थापित नहीं कर सकता: * ns * सेट के साथ * –

0

आप किसी मैक्रो लिख सकते हैं कि नकल

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

यह बेहतर काम करता है क्योंकि प्रतीक एस के संकल्प संदर्भ में होता है जो my-eval पर कॉल करता है। स्पष्टीकरण के लिए @ माथियास बेनकार्ड के लिए धन्यवाद।

1

(प्रतीक (str "ग्राहक" (गणित/पेट (.nextInt यादृच्छिक)))

मैं बस, जोड़ना चाहते थे कि इस

(gensym "client-") 

साथ प्राप्त किया जा सकता है (मैं टिप्पणी करना चाहता था, लेकिन यह हमें बदलता है कि मैं नहीं कर सकता :))

संबंधित मुद्दे