2010-03-17 18 views
9

में "Perl Best Practices" AutoLoad पर खंड में बहुत पहली पंक्ति है:मुझे पर्ल के ऑटोोलॉड का उपयोग कब करना चाहिए?

AutoLoad

हालांकि सभी मामलों में वह वर्णन करता OO या मॉड्यूल के साथ काम कर रहे हैं प्रयोग न करें।

मेरे पास एक स्टैंड स्टैंड अकेली स्क्रिप्ट है जिसमें कुछ कमांड लाइन नियंत्रण स्विच करती है जो विशेष कार्यों के संस्करण परिभाषित करती हैं। अब मुझे पता है कि मैं बस सशर्त और evals ले सकता हूं और सब कुछ से पहले मेरी फाइल के शीर्ष पर नग्न चिपका सकता हूं, लेकिन मुझे फ़ाइल के अंत में ऑटोोलॉइड में रखने के लिए सुविधाजनक और क्लीनर लगता है।

क्या यह बुरा अभ्यास/शैली है? यदि आप ऐसा सोचते हैं तो क्यों, और ऐसा करने का एक और तरीका है?

ब्रायन के अनुरोध

के अनुसार मैं मूल रूप से इस का उपयोग कर रहा कमांड लाइन स्विच के आधार पर सशर्त संकलन करने के लिए।

मुझे कुछ रचनात्मक आलोचना नहीं है।

sub AUTOLOAD { 
    our $AUTOLOAD; 

    (my $method = $AUTOLOAD) =~ s/.*:://s; # remove package name 
    if ($method eq 'tcpdump' && $tcpdump) { 
     eval q(
     sub tcpdump { 
      my $msg = shift; 
      warn gf_time()." Thread ".threads->tid().": $msg\n"; 
     } 
     ); 
    } elsif ($method eq 'loginfo' && $debug) { 
     eval q(
     sub loginfo { 
      my $msg = shift; 
      $msg =~ s/$CRLF/\n/g; 
      print gf_time()." Thread ".threads->tid().": $msg\n"; 
     } 
     ); 
    } elsif ($method eq 'build_get') { 
     if ($pipelining) { 
      eval q(
      sub build_get { 
       my $url = shift; 
       my $base = shift; 
       $url = "http://".$url unless $url =~ /^http/; 
       return "GET $url HTTP/1.1${CRLF}Host: $base$CRLF$CRLF"; 
      }  
      ); 
     } else { 
      eval q( 
      sub build_get { 
       my $url = shift; 
       my $base = shift; 
       $url = "http://".$url unless $url =~ /^http/; 
       return "GET $url HTTP/1.1${CRLF}Host: $base${CRLF}Connection: close$CRLF$CRLF"; 
      }  
      ); 
     }  
    } elsif ($method eq 'grow') { 
     eval q{ require Convert::Scalar qw(grow); }; 
     if ([email protected]) { 
      eval q(sub grow {}); 
     } 
     goto &$method; 
    } else { 
     eval "sub $method {}"; 
     return; 
    } 
    die [email protected] if [email protected]; 
    goto &$method; 
} 
+1

आप जो कर रहे हैं उसका एक उदाहरण चर्चा में सुधार करेगा। :) –

उत्तर

1

यदि AUTOLOAD का उपयोग करने का आपका एकमात्र कारण ब्लॉक को अंत में स्थानांतरित करना है, तो इसे एक उपराउटिन में अंत में क्यों न रखें, और उसके बाद इसके आश्रित चर परिभाषित किए जाने पर इसे कॉल करें?

sub tcpdump; # declare your subs if you want to call without parens 

# define the parameters 

compile(); 

# code that uses new subs 

sub compile { 
    *tcpdump = $tcpdump ? sub { 
     my $msg = shift; 
     warn gf_time()." Thread ".threads->tid().": $msg\n"; 
    } : sub {}; 
    # ... 
} 
# EOF 

अभी भी बेहतर है, अगर वैश्विक कहीं और की जरूरत नहीं कर रहे हैं, बस मूल्यों compile को तर्क के रूप में गुजरती हैं।

+0

@ एरिक स्ट्रॉम: तो आपको लगता है कि यह 'ऑटोोलॉइड' की तुलना में बेहतर शैली और क्लीनर है? ऐसा लगता है कि मैं 'ऑटोोलॉइड' के साथ क्या कर रहा हूं, इसके अलावा मैं व्यावहारिक रूप से समान हूं, सिवाय इसके कि मुझे प्रोग्राम की शुरुआत में स्पष्ट रूप से 'संकलन' को कॉल करना होगा। फ़ंक्शन कहने पर पहली बार 'ऑटोोलॉइड' को कॉल करने से बेहतर क्यों है? बहुत ही रोचक समाधान क्योंकि मैंने पहले '* name = sub {...} 'वाक्यविन्यास नहीं देखा था। –

+1

@ रॉबर्ट एसबार्न्स => 'ऑटोोलॉड' इसके साथ सामान का थोड़ा सा सामान रखता है: विरासत, गति के साथ जटिलताओं, जिसे सबस को विधियों के रूप में बुलाया जाना आवश्यक है। वे सभी आवश्यक बुराई हैं यदि आप ऐसा कुछ कर रहे हैं जिसे वास्तव में 'ऑटोोलॉइड' की आवश्यकता है, लेकिन यदि नहीं, तो यह केवल बग का स्रोत हो सकता है। काम करता है कि सबसे सरल समाधान करने के लिए सबसे अच्छा है। अलग-अलग, स्ट्रिंग eval के बजाय एनन उप वाक्यविन्यास का उपयोग करते हुए पर्ल को रनटाइम के बजाए संकलन समय पर त्रुटियों को पकड़ने की अनुमति मिलती है। –

6

मुझे लगता है कि अकेले स्टैंड स्क्रिप्ट के लिए यह दृष्टिकोण ठीक है। आप तेज़ी आगामी कॉल तेजी लाने के लिए, उदा .:

sub AUTOLOAD { 
    (my $name = our $AUTOLOAD) =~ s/.*:://; 
    no strict 'refs'; # allow symbolic references 

    *$AUTOLOAD = sub { print "$name subroutine called\n" };  
    goto &$AUTOLOAD; # jump to the new sub 
} 

Autoloading मुश्किल जब विरासत के पेड़ का निर्माण है पर सबरूटीन्स बना सकते हैं।

7

एक वैकल्पिक रणनीति के लिए App :: * मॉड्यूल के रूप में स्क्रिप्ट लिखने और कमांडलाइन विकल्प जो वर्ग प्रदान करने के लिए जो कुछ भी कार्यक्षमता यह है कि विकल्प के आधार पर प्लगेबल है लोड करने के लिए चुनें करने के लिए किया जाएगा। आप require उस वर्ग को केवल एक बार जब आप जानते हैं कि यह कौन सा है। यह थोड़ा और आगे का काम है, लेकिन यदि आप लंबे समय तक स्क्रिप्ट को बनाए रखना चाहते हैं, तो मुझे लगता है कि यह भुगतान करेगा। पिछले कुछ वर्षों लिपियों जिसकी कार्यक्षमता वास्तव में, मॉड्यूल में रहती है App::Cmd, MooseX::Getopt, और the bastard offspring of both सहित बनाने के लिए कुछ अतिरिक्त अच्छा उपकरण के निर्माण को देखा है।

+0

दिलचस्प और मूल्यवान लग रहा है, हालांकि मुझे लगता है कि मैं जो कर रहा हूं उसके लिए यह अधिक हो सकता है। यह केवल 500 लाइन स्क्रिप्ट के बारे में है। –

+0

500 तर्कसंगत 450 के बारे में बहुत अधिक है। :) – hobbs

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