2011-07-30 6 views
9

मान लें कि मैं कई घटकों के साथ एक बड़ी क्लोजर लाइब्रेरी बनाना चाहता हूं। एक डेवलपर के रूप में, मैं कई घटकों को अलग-अलग नामस्थानों में रखना चाहता हूं क्योंकि कई सहायक कार्यों के समान नाम हो सकते हैं। मैं जरूरी चीजों को निजी बनाना नहीं चाहता क्योंकि उनके पास अत्यधिक मामलों में उपयोगिता हो सकती है और निजी के पीछे काम-आसपास अच्छा नहीं है। (दूसरे शब्दों में, मैं कोड उपयोग का सुझाव देना चाहता हूं, पूरी तरह से उपयोग को रोक नहीं सकता।)सार्वजनिक खपत के लिए क्लोजर पुस्तकालयों का निर्माण करते समय आप फ़ंक्शन नाम कैसे व्यवस्थित करते हैं?

हालांकि, मैं पुस्तकालय के उपयोगकर्ताओं को कई कार्यों के सबसेट के संघ के साथ नामस्थान में काम करना चाहता हूं प्रत्येक उप पुस्तकालय। ऐसा करने के लिए बेवकूफ या सबसे अच्छा तरीका क्या है? मेरे दिमाग में आने वाला एक समाधान है जो उत्पन्न करता है एक मैक्रो लिखना: आवश्यक नामों की किसी दिए गए सूची को परिभाषित करके एक नया वैर मैपिंग बनाना आवश्यक है (पहले कोड उदाहरण देखें)। क्या इस विधि के साथ ट्रेडऑफ हैं जैसे कि विस्तार के प्रकार क्या होता है? क्या कोई बेहतर तरीका है (या निर्मित)?

मैक्रो उदाहरण (src/mylib/public.clj):

(ns mylib.public 
    (:require [mylib.a :as a]) 
    (:require [mylib.b :as b])) 

(transfer-to-ns [+ a/+ 
        - b/- 
        cat b/cat 
        mapper a/mapper]) 

फिर से, स्पष्ट करने के लिए, अंतिम लक्ष्य बनाने के लिए सक्षम होने के लिए mylib के उपयोगकर्ताओं द्वारा बनाए गए अन्य परियोजनाओं में कुछ फ़ाइल के लिए किया जाएगा की तरह कुछ (src/someproject/core.clj):

(ns someproject.core 
    (:require [mylib.public :as mylib])) 

(mylib/mapper 'foo 'bar) 

@Jeremy दीवार, ध्यान दें कि आपके प्रस्तावित समाधान मेरी जरूरतों fullfill नहीं है। आइए मान लें कि निम्न कोड मौजूद है।

mylib/a.clj:

(ns mylib.a) 

(defn fa [] :a) 

mylib/b.clj:

(ns mylib.b) 

(defn fb [] :b) 

mylib/public.clj:

(ns mylib.public 
    (:use [mylib.a :only [fa]]) 
    (:use [mylib.b :only [fb]])) 

somerandomproject/core.clj: (मान लें कि क्लासपाथ सही तरीके से सेट हैं)

(ns somerandomproject.core 
    (:require [mylib.public :as p]) 

;; somerandomproject.core=> (p/fa) 
;; CompilerException java.lang.RuntimeException: No such var: p/fa, compiling:  (NO_SOURCE_PATH:3) 
;; somerandomproject.core=> (mylib.a/fa) 
;; :a 

यदि आप नोटिस करते हैं, mylib/public.clj में "उपयोग" फ़ंक्शन public.clj को इन वर्रों को उपयोगकर्ता फ़ाइल somerandomproject/core.clj पर प्रदान करने की अनुमति नहीं देते हैं।

उत्तर

9

आप इसे कैसे Compojure या Lamina की तरह एक पुस्तकालय अपने "सार्वजनिक" एपीआई का आयोजन को देखने के लिए दिलचस्प लग सकते हैं का उपयोग करें।

पत्ता lamina.api की तरह "सार्वजनिक" नामस्थान कि उर्फ ​​की सेवा lamina.core.pipeline की तरह "आंतरिक" नामस्थान से कार्य (ज़ैक का आयात fn उसकी Potemkin पुस्तकालय से उपयोग करते हुए) है। कुछ दस्तावेज़ों के साथ, यह सार्वजनिक रूप से सामने वाले एनएस को संभावित रूप से बदलने वाले आंतरिक से स्पष्ट रूप से चित्रित करता है।मुझे इस रणनीति में बड़ी कमी आई है कि आयात-एफएन इसे कार्यान्वयन में किसी फ़ंक्शन के उपयोग से चलने (emacs में) चलना और अधिक कठिन बनाता है। या उदाहरण के लिए clojure.repl/स्रोत का उपयोग करने के लिए कौन सा फ़ंक्शन पता है।

कंपोज़र जैसी लाइब्रेरी फ़ंक्शन के सार्वजनिक/निजी हिस्सों को अलग करने के लिए निजी वर्र्स का उपयोग करती है (उदाहरण के लिए compojure.core देखें)। "निजी" कार्यों के साथ बड़ी कमी यह है कि बाद में आप पाते हैं कि आप उन्हें बेनकाब करना चाहते हैं या यह परीक्षण को और अधिक जटिल बनाता है। यदि आप कोड बेस को नियंत्रित करते हैं, तो मुझे निजी पहलुओं को एक बड़ा सौदा नहीं मिलता है। निजी फ़ंक्शन को संदर्भित करने के लिए परीक्षण समस्या आसानी से # 'foo.core/my-function का उपयोग कर काम कर रही है।

आम तौर पर मैं लैमिना की तुलना में कंपोजर की शैली की तरह कुछ और उपयोग करता हूं लेकिन ऐसा लगता है जैसे आप लैमिना की तरह कुछ और पसंद करेंगे।

+0

अच्छा उत्तर देखें। यह वही है जो मैं था तलाश कर रहा हूं। मैंने पहले compojure.core शैली की कोशिश की है लेकिन आप जिन सीमाओं के बारे में बात करते हैं, उनके साथ मारा गया था, इसलिए मैं संभावित विकल्पों की तलाश में था। मैं लैमिना की जांच करूंगा और देख सकता हूं कि यह स्वीकार करने से पहले कैसे काम करता है। – bmillare

+0

कैस्कलॉग इसी तरह के साथ आयोजित किया जाता है लैमिना के लिए रेखाएं लेकिन थोड़ा कम सख्ती से - आपको जो मुख्य चीजें चाहिए, वह कैस्कलॉग.एपीआई एनएस में या उसके अंदर है या नहीं, लेकिन आप अधिक उन्नत कार्यक्षमता के लिए अंतर्निहित एनएस में भी पहुंच सकते हैं। –

2

मुझे बिल्कुल यकीन नहीं है कि आप यहां क्या पूछ रहे हैं। मुझे लगता है कि आप जानना चाहते हैं कि साझा उपयोगिता कार्यों के लिए नामस्थान से प्रकाशन आयात करने का सबसे अच्छा अभ्यास क्या है? उस मामले में उल्लेख समारोह आप के लिए मुझे लगता है कि क्या देख रहे है: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/refer

(refer mylib.a :only [+]) 
(refer mylib.b :only [-]) 

यह वर्तमान नाम स्थान में एक नाम स्थान में सार्वजनिक आइटम आयात करता है। हालांकि पसंदीदा तरीका एक साथ अपने नाम स्थान घोषणा में यह करने के लिए होगा: निर्देश

(ns (:use (mylib.a :only [+]) 
      (mylib.b :only [-]))) 
+0

विचार उपयोगकर्ताओं के लिए एक नामस्थान बनाने के लिए है। यह उस clj फ़ाइल को विकसित करने के लिए नहीं है, लेकिन अन्य clj फ़ाइलों को विकसित करना जहां उन्हें आपके द्वारा बनाई गई फ़ाइल की आवश्यकता होगी या उपयोग करें। तो मेरे उदाहरण में, आप एनएस फॉर्म में होंगे, जैसे कुछ (: mylib.public: mylib के रूप में] – bmillare

+0

आपका प्रस्तावित समाधान मेरी आवश्यकताओं को पूरा नहीं करता है, कृपया स्पष्टीकरण – bmillare

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