2009-06-10 11 views
24

मैं क्लोजर में डबलिंग कर रहा हूं और इस सामान्य पायथन मुहावरे के समतुल्य क्लोजर (और/या लिस्प) को निर्धारित करने में थोड़ा परेशानी कर रहा हूं।पाइथन मुहावरे के बराबर क्लोजर क्या है "अगर __name__ == '__main__'"?

# mymodule.py 
class MyClass(object): 
    """Main logic/code for the library lives here""" 
    pass 

def _runTests(): 
    # Code which tests various aspects of MyClass... 
    mc = MyClass() # etc... 
    assert 2 + 2 == 4 

if __name__ == '__main__': _runTests() 

यह सरल, विज्ञापन के लिए उपयोगी है:

मुहावरा वहाँ अक्सर परीक्षण कोड का एक सा है एक अजगर मॉड्यूल के तल पर है कि, और उसके बाद एक बयान जो उदाहरण के लिए कोड चलाता है, है - परीक्षण। एक आम तौर पर from mymodule import MyClass लिखकर इस मॉड्यूल का उपयोग करेगा, जिस स्थिति में _runTests() कभी नहीं कहा जाता है, लेकिन अंत में स्निपेट के साथ, कोई भी कमांड लाइन से python mymodule.py टाइप करके इसे चला सकता है।

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

उत्तर

27

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

आप रन यूनिट परीक्षणों जैसी चीजों को करने के लिए आसानी से कार्य लिख सकते हैं, और जब भी आप उन्हें चलाने के लिए आरईपीएल से उन कार्यों को कॉल करते हैं और अन्यथा अनदेखा करते हैं। क्लोजर में clojure.contrib.test-is का उपयोग करना आम है, अपने टेस्ट फ़ंक्शंस को अपने नेमस्पेस में जोड़ें, फिर उन्हें चलाने के लिए clojure.contrib.test-is/run-tests का उपयोग करें।

कमांडलाइन से क्लोजर चलाने के लिए एक और अच्छा कारण यह नहीं है कि जेवीएम का स्टार्टअप समय निषिद्ध हो सकता है।

यदि आप वास्तव में कमांड लाइन से क्लोजर स्क्रिप्ट चलाने के लिए चाहते हैं, तो आप इसे कई तरीकों से कर सकते हैं। कुछ चर्चाओं के लिए the Clojure mailing list देखें।

कमांड लाइन तर्कों की उपस्थिति के लिए परीक्षण करना एक तरीका है। मौजूदा निर्देशिका में इस foo.clj को देखते हुए:

(ns foo) 

(defn hello [x] (println "Hello," x)) 

(if *command-line-args* 
    (hello "command line") 
    (hello "REPL")) 

आप निर्भर करता है कि आप Clojure शुरू अलग व्यवहार मिलेगा।

$ java -cp ~/path/to/clojure.jar:. clojure.main foo.clj -- 
Hello, command line 
$ java -cp ~/path/to/clojure.jar:. clojure.main 
Clojure 1.1.0-alpha-SNAPSHOT 
user=> (use 'foo) 
Hello, REPL 
nil 
user=> 

Clojure स्रोत में src/clj/clojure/main.clj देखें कि आप को देखने के लिए कि यह कैसे काम कर रहा है चाहता हूँ।

एक और तरीका है अपने कोड को .class फ़ाइलों में संकलित करना और उन्हें जावा कमांड लाइन से आमंत्रित करना है। एक स्रोत फ़ाइल foo.clj को देखते हुए:

(ns foo 
    (:gen-class)) 

(defn hello [x] (println "Hello," x)) 

(defn -main [] (hello "command line")) 

संकलित .class फ़ाइलों को स्टोर करने के लिए एक निर्देशिका करते हैं; यह ./classes पर डिफ़ॉल्ट है। आपको यह फ़ोल्डर स्वयं बनाना होगा, क्लोजर इसे नहीं बनाएगा। यह भी सुनिश्चित करें कि $CLASSPATH को ./classes और आपके स्रोत कोड के साथ निर्देशिका शामिल करने के लिए सेट करें; मुझे लगता है कि foo.clj वर्तमान निर्देशिका में है। तो कमांड लाइन से:

$ mkdir classes 
$ java -cp ~/path/to/clojure.jar:./classes:. clojure.main 
Clojure 1.1.0-alpha-SNAPSHOT 
user=> (compile 'foo) 
foo 

classes निर्देशिका में आप अब .class फाइलों का एक समूह होगा।

$ java -cp ~/path/to/clojure.jar:./classes foo 
Hello, command line. 

वहाँ clojure.org पर Clojure कोड संकलन के बारे में जानकारी का एक बहुत कुछ है: कमांड लाइन (डिफ़ॉल्ट रूप से -main समारोह चल रहा है) से अपने कोड को लागू करने के लिए।

1

मैं क्लोजर के लिए बहुत नया हूं लेकिन मुझे लगता है कि क्लोजर समूहों पर this discussion एक समाधान और/या कामकाज हो सकता है, विशेष रूप से 17 अप्रैल को 10:40 बजे स्टुअर्ट सिएरा द्वारा पोस्ट किया जा सकता है।

0

आप क्लोजर-कॉन्ट्रिब से test-is लाइब्रेरी को देखना चाहते हैं। यह एक ही मुहावरे नहीं है, लेकिन इसे एक सुंदर समान वर्कफ़्लो का समर्थन करना चाहिए।

1

सामान्य लिस्प में आप features के साथ सशर्त पढ़ने का उपयोग कर सकते हैं।

#+testing (run-test 'is-answer-equal-42) 

से ऊपर ही पढ़ा जाएगा और इस तरह लोड होने के दौरान निष्पादित करता है, तो सुविधाओं की सूची cl:*features* करने के लिए बाध्य प्रतीक शामिल होंगे: परीक्षण।

उदाहरण

लिए
(let ((*features* (cons :testing *features*))) 
    (load "/foo/bar/my-answerlib.lisp")) 

अस्थायी रूप से जोड़ देगा: स्थानों की सूची के लिए परीक्षण।

आप अपनी खुद की विशेषताओं को परिभाषित कर सकते हैं और सामान्य लिस्प सिस्टम को कौन सा अभिव्यक्ति पढ़ता है और कौन सा छोड़ देता है इसे नियंत्रित कर सकते हैं।

साथ ही आप भी कर सकते हैं:

#-testing (print '|we are in production mode|) 
+0

मुझे नहीं लगता कि * विशेषताएं * इसके लिए अच्छे हैं। * विशेषताएं * उपलब्ध सुविधाओं को दिखाएं, कुछ पर्यावरण स्थिति या कोड चलाने का अनुरोध नहीं। –

+0

क्यों नहीं? * विशेषताएं * सभी प्रकार की सामग्री के लिए उपयोग की जाती है: हार्डवेयर का वर्णन करने के लिए, कुछ मूल libs उपलब्ध हैं, सॉफ़्टवेयर के कुछ तरीके, लिस्प कार्यान्वयन का संस्करण, भाषा का संस्करण, चाहे वह है: उत्पादन- मोड या: विकास-मोड, आदि –

0

कॉमन लिस्प और Clojure (और साथ ही अन्य lisps) आरईपीएल के साथ इंटरैक्टिव वातावरण प्रदान करते हैं, और आप «if __name__ == '__main__'» की तरह चालें जरूरत नहीं है। पाइथन के लिए आरईपीएल जैसे वातावरण हैं: कमांड लाइन, आईपीथॉन, पायदान मोड से इमेक्स इत्यादि,

आपको केवल लाइब्रेरी बनाना चाहिए, इसमें एक टेस्टाइट जोड़ें (सामान्य लिस्प के लिए कई परीक्षण ढांचे हैं ; मैं 5am ढांचे को प्राथमिकता देता हूं, here उपलब्ध ढांचे का एक सर्वेक्षण है)। और फिर आप पुस्तकालय को लोड करते हैं, और आरईपीएल में आप लाइब्रेरी के साथ कुछ भी कर सकते हैं: रन परीक्षण, कॉल फ़ंक्शंस, प्रयोग इत्यादि।

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

:

(def-suite sqlite-suite) 

(defun run-all-tests() 
    (run! 'sqlite-suite));' 

(in-suite sqlite-suite) 

(test test-connect 
    (with-open-database (db ":memory:"))) 

(test test-disconnect-with-statements 
    (finishes 
    (with-open-database (db ":memory:") 
     (prepare-statement db "create table users (id integer primary key, user_name text not null, age integer null)")))) 
... 

और इंटरैक्टिव सत्र:

CL-USER> (sqlite-tests:run-all-tests) 
....... 
Did 7 checks. 
    Pass: 7 (100%) 
    Skip: 0 (0%) 
    Fail: 0 (0%) 

NIL 
CL-USER> (defvar *db* (sqlite:connect ":memory:")) 
*DB* 
CL-USER> (sqlite:execute-non-query *db* "create table t1 (field text not null)") 
; No value 
CL-USER> (sqlite:execute-non-query *db* "insert into t1 (field) values (?)" "hello") 
; No value 
CL-USER> (sqlite:execute-to-list *db* "select * from t1") 
(("hello")) 
CL-USER> 

अब जब कि मैंने पाया लगता

यहाँ (मेरे सीएल-SQLite पुस्तकालय से) कॉमन लिस्प के लिए एक उदाहरण है sqlite में बग: निष्पादित करने के लिए सूची। मैं इस फ़ंक्शन के कोड पर जाता हूं, बग को ठीक करता हूं और इस फ़ंक्शन को पुनः संकलित करता हूं। फिर मैं निश्चित कार्य कहता हूं और यह सुनिश्चित करता हूं कि यह काम करता है। इन-मेमोरी डेटाबेस नहीं चला है, यह वही स्थिति है जैसा कि इसे पुन: संकलित करने से पहले था।

+3

__name __ == '__ मुख्य__' मुहावरे वास्तव में आरईपीएल के साथ कुछ भी नहीं करना है - यह "मॉड्यूल के रूप में आयातित" और "स्क्रिप्ट के रूप में चलाने" के बीच अंतर करने की एक विधि है। इसमें कोड आम तौर पर नूडलिंग और परीक्षण कोड नहीं है जिसे आप आरईपीएल में प्रयोग करेंगे, लेकिन कोड जिसे आप बार-बार निष्पादित करना चाहते हैं। टेस्ट कोड एक उदाहरण है, लेकिन सबसे आम तौर पर एक स्क्रिप्ट होती है जो मॉड्यूल के रूप में पुन: उपयोग की अनुमति देती है। – Brian

+0

हां, आम तौर पर, वे अलग-अलग चीजें हैं। लेकिन इस सवाल के संदर्भ में, __name__ को जांचने के लिए परीक्षण (और फिर से चलाने) परीक्षणों के लिए प्रयोग किया गया था, और आरईपीएल लिस्प्स में ऐसे उपयोग के मामले के लिए बेवकूफ है। –

+0

उपयोगकर्ता ने नाम == मुख्य मुहावरे के लिए पूछा, एक प्रतिलिपि नहीं, एक परीक्षण सूट नहीं। – mcandre

-3

आप एक "प्रवेश बिंदु" होने के बारे में बात कर रहे हैं, तो आप निश्चित रूप से ऐसा कर सकते हैं:

(ns foo) 

(defn foo [n] 
    (inc n)) 

(defn main [] 
    (println "working") 
    (println "Foo has ran:" (foo 1))) 

(main) 

अब क्या होगा किसी भी समय इस कोड है (लोड फ़ाइल "foo.clj") ' डी या ('foo का उपयोग करें) या (' foo की आवश्यकता है), फिर (मुख्य) कहा जाएगा, जो आमतौर पर नहीं किया जाता है।

अधिक आम बात यह है कि कोड की एक फ़ाइल आरईपीएल पर लोड की जा सकती है और फिर मुख्य समारोह उपयोगकर्ता द्वारा बुलाया जाएगा।

+0

क्या यह इस तरह से किया जा सकता है कि (मुख्य) केवल तब ट्रिगर किया जाता है जब foo.clj सीधे चलाया जाता है और जब कोई अन्य स्क्रिप्ट लोड नहीं होती है? – mcandre

+0

मुझे ऐसा नहीं लगता क्योंकि दोनों मामलों में आप सभी अभिव्यक्तियों का मूल्यांकन (और फिर संकलित) करेंगे। हमेशा एओटी संकलन होता है जो एक प्रविष्टि-बिंदु की परिभाषा की अनुमति देता है: http://clojure.org/compilation – Chris

0

Boot एक बिल्ड टूलींग (लीइंगिंग का विकल्प) है, जो supports scripts है। तो आपके पास #!/usr/bin/env boot से शुरू होने वाली बूट स्क्रिप्ट हो सकती है जिसमें -main विधि हो सकती है।

आप कमांड लाइन से भी कार्यवाही कर सकते हैं जो आपके कोड के विभिन्न कार्यों को कॉल करेगा। और आपके पास एक पैकेजिंग कार्य हो सकता है जो इन कार्यों में से एक के लिए प्रवेश बिंदु के रूप में uberjar बना सकता है।