2015-06-03 8 views
6

मैं एक शिक्षण अनुभव के रूप में रैकेट को Python स्क्रिप्ट पोर्टिंग कर रहा हूँ, और मैं इस समारोह है:मैं यह रैकेट कोड DRYER कैसे बनाऊंगा?

(define (check-status) 
    (define git [find-executable-path "git"]) 
    (define-values (ckot out in err) 
     (subprocess #f #f #f git "checkout" "-q" "master")) 
    (define-values (local lout lin lerr) 
     (subprocess #f #f #f git "rev-parse" "@")) 
    (define-values (remote rout rin rerr) 
     (subprocess #f #f #f git "rev-parse" "@{u}")) 
    (define-values (merge-base mbout mbin mberr) 
     (subprocess #f #f #f git "merge-base" "@" "@{u}")) 
    (display-lines (port->lines mbout)) 
    (define ports '(ckot out in err local lout lin lerr remote rout rin rerr merge-base mbout mbin mberr)) 
    (map (lambda (x) 
     (cond ((input-port? x) (close-input-port x)) 
       ((output-port? x) (close-output-port x)))) ports)) 

समस्या यह है कि यह बहुत ही सूखी नहीं है।

(define (check-status) 
    (define commands '(
         '("checkout" "-q" "master") 
         '("rev-parse" "@") 
         '("rev-parse" "@{u}") 
         '("merge-base" "@" "@{u}")) 
    (map currently-immaginary-git-command-fn commands)) 
: जब से मैं एक लिस्प उपयोग कर रहा हूँ, और लिस्प पागल काम करने के लिए सक्षम होने के लिए जाना जाता है, मैं वहाँ सब उपप्रक्रिया कोड ले और उसे निकालने के तो मैं क्या कर सकते हैं की तरह कुछ करने के लिए एक तरीका है जानना चाहता हूँ

और आदेशों की सूची में प्रत्येक कमांड के आउटपुट की एक सूची के साथ समाप्त होता है। यह मैं कैसे करूंगा? चूंकि मैं पूरी लिस्प/स्कीम चीज में नया हूं, इसलिए मैं सिंटैक्स को समझ रहा हूं क्योंकि मैं जाता हूं और मुझे उपलब्ध संसाधनों से पूरी तरह से अवगत नहीं है।

+0

यह [स्टैक एक्सचेंज कोड रिव्यू] (https://codereview.stackexchange.com/) के लिए एक अच्छा सवाल होगा। –

+0

यह पहले से ही एक स्वीकार्य उत्तर है, हालांकि @ जोनाथन को अपना कामकाजी कोड लेने और कोड समीक्षा पर पोस्ट करने के लिए आपका स्वागत है, अगर वह चाहता है कि यह – Phrancis

+0

बीटीडब्लू की समीक्षा करे, तो पोर्ट-क्लोजिंग कोड काम नहीं करेगा: '' (बाहर निकलना। ..) 'प्रतीकों की एक सूची है; यह '(सूची 'ckot' out 'में समान है ...)'। आप इसके बजाय '(सूची ckot बाहर ...) 'चाहते हैं। –

उत्तर

6

सबसे पहले, क्लीनर समाधान के साथ आने के लिए आपके लिए अच्छा है! आप सही हैं कि आपने जो प्रयास किया है, उसे करने का एक और शानदार तरीका है।

प्रारंभ करने के लिए, subprocess का उपयोग करके अपने विशेष उपयोग-मामले में लगभग निश्चित रूप से अधिक है। racket/system मॉड्यूल एक सरल इंटरफ़ेस प्रदान करता है जो आपकी आवश्यकताओं के लिए पर्याप्त होना चाहिए। विशेष रूप से, मैं system* फ़ंक्शन का उपयोग करता हूं, जो प्रदत्त तर्कों के साथ एक एकल प्रक्रिया निष्पादित करता है, फिर अपने आउटपुट को stdout पर प्रिंट करता है।

system* का उपयोग करना, एक बहुत ही सामान्य सहायक फ़ंक्शन बनाना संभव है जो किसी विशेष निष्पादन योग्य के लिए कमांड निष्पादित कर सकता है और स्ट्रिंग के रूप में अपना आउटपुट लौटा सकता है।

(define (execute-command proc-name) 
    (define proc (find-executable-path proc-name)) 
    (λ (args) 
    (with-output-to-string 
    (thunk (apply system* proc args))))) 

यह समारोह अपने आप में एक नई समारोह जब यह कहा जाता है देता है। इसका मतलब है कि गिट कमांड को कॉल करने के लिए इसका उपयोग इस तरह दिखेगा:

((execute-command "git") '("checkout" "-q" "master")) 

इसका कारण जल्द ही स्पष्ट हो जाएगा।

असल execute-command के कार्यान्वयन को देखते हुए, हम with-output-to-string का प्रयोग कर एक स्ट्रिंग में (के बजाय सिर्फ यह मुद्रण stdout करने के लिए) system* कॉल से उत्पादन के सभी पुनर्निर्देशित करने के लिए। current-output-port पैरामीटर सेट करने के लिए यह वास्तव में parameterize का उपयोग करने का संक्षिप्त नाम है, लेकिन यह आसान है।

इस फ़ंक्शन के साथ, हम check-status को बहुत आसानी से कार्यान्वित कर सकते हैं।

(define (check-status) 
    (define commands 
    '(("checkout" "-q" "master") 
     ("rev-parse" "@") 
     ("rev-parse" "@{u}") 
     ("merge-base" "@" "@{u}"))) 
    (map (execute-command "git") commands)) 

अब (execute-command "git") वापसी होने एक नया कार्य स्पष्ट हो जाता है के लिए कारण: हम उस का उपयोग एक समारोह जो तब commands सूची पर नक्शा तार की एक नई सूची का निर्माण करने के बनाने के लिए कर सकते हैं।

इसके अलावा, ध्यान दें कि commands सूची की परिभाषा केवल शुरुआत में एक ही ' का उपयोग करती है। आपके द्वारा प्रदान की गई परिभाषा काम नहीं करेगी, और वास्तव में, आपके मूल कार्यान्वयन में परिभाषित ports सूची वह नहीं है जो आप उम्मीद करेंगे। ऐसा इसलिए है क्योंकि '(...) बिल्कुल (list ...)-वे अलग हैं, इसलिए उनका उपयोग करते समय सावधान रहें।

+0

बहुत बढ़िया ! धन्यवाद। मजेदार, मुझे लगा कि यह एक समारोह या मैक्रोज़ लौटने के साथ कुछ करने के लिए होगा। – Jonathan