पर्ल 5 के फ़ंक्शन प्रोटोटाइप खराब क्यों हैं?


116

में एक और स्टैक ओवरफ़्लो सवाल लियोन Timmermans माँगे:

मैं आपको सलाह दूंगा कि आप प्रोटोटाइप का उपयोग न करें। उनके पास उनके उपयोग हैं, लेकिन अधिकांश मामलों के लिए नहीं और निश्चित रूप से इस एक में नहीं।

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


मैं भी उत्सुक हूँ। एकमात्र समय जब मैं उनका उपयोग नहीं करता हूं, जब मैं एक चर संख्या के तर्क के साथ बुला रहा होता हूं।
पॉल टॉम्बलिन

7
क्या मैं कृपया यह सलाह दे सकता हूं कि आप लेख पढ़ें, "पर्ल प्रोटोटाइप्स को माना हानिकारक" ?
tchrist 12

जवाबों:


121

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

प्रोटोटाइप आपको उन कार्यों को परिभाषित करने की अनुमति देता है जो अंतर्निहित कार्यों की तरह व्यवहार करते हैं।

  • कोष्ठक वैकल्पिक हैं।
  • दलीलों पर प्रसंग लगाया जाता है।

उदाहरण के लिए, आप एक फ़ंक्शन को इस तरह परिभाषित कर सकते हैं:

sub mypush(\@@) { ... }

और इसे कॉल करें

mypush @array, 1, 2, 3;

\सरणी के लिए एक संदर्भ लेने के लिए लिखने की आवश्यकता के बिना ।

संक्षेप में, प्रोटोटाइप आपको अपनी स्वयं की कृत्रिम चीनी बनाने देता है। उदाहरण के लिए मूस फ्रेमवर्क एक अधिक विशिष्ट OO सिंटैक्स का अनुकरण करने के लिए उनका उपयोग करता है।

यह बहुत उपयोगी है लेकिन प्रोटोटाइप बहुत सीमित हैं:

  • उन्हें संकलन-समय पर दिखाई पड़ता है।
  • उन्हें बाईपास किया जा सकता है।
  • तर्कों के संदर्भ में प्रचार करने से अप्रत्याशित व्यवहार हो सकता है।
  • वे कड़ाई से निर्धारित फ़ॉर्म के अलावा किसी अन्य चीज़ का उपयोग करके कार्यों को कॉल करना मुश्किल बना सकते हैं।

देखें प्रोटोटाइप सभी रक्तमय जानकारी के लिए perlsub में।


2
मैंने इस उत्तर को स्वीकार कर लिया है क्योंकि मुझे लगता है कि यह सवाल का सबसे अच्छा जवाब देता है - प्रोटोटाइप आंतरिक रूप से खराब नहीं हैं, यह सिर्फ यह है कि आप उनका उपयोग कैसे करते हैं।
अलंकृत 19

2
दूसरी ओर मूस प्रोटोटाइप, / भयानक / p3rl.org/MooseX::Declare p3rl.org/MooseX::Method::Signactions
Kent Fredric


तो वे एक मिथ्या नाम हैं, फिर?
पीटर मोर्टेंसन

69

समस्या यह है कि पर्ल के फंक्शन प्रोटोटाइप वे नहीं करते जो लोग सोचते हैं कि वे करते हैं। उनका उद्देश्य आपको उन कार्यों को लिखने की अनुमति देता है जिन्हें पर्ल के अंतर्निहित कार्यों की तरह पार्स किया जाएगा।

सबसे पहले, विधि कॉल पूरी तरह से प्रोटोटाइप को अनदेखा करती है। यदि आप OO प्रोग्रामिंग कर रहे हैं, तो इससे कोई फर्क नहीं पड़ता कि आपके तरीकों में क्या प्रोटोटाइप है। (इसलिए उनके पास कोई प्रोटोटाइप नहीं होना चाहिए।)

दूसरा, प्रोटोटाइप सख्ती से लागू नहीं किए गए हैं। यदि आप एक सबरूटीन कहते हैं &function(...), तो प्रोटोटाइप को अनदेखा कर दिया जाता है। इसलिए वे वास्तव में किसी भी प्रकार की सुरक्षा प्रदान नहीं करते हैं।

तीसरा, वे डरावना एक्शन-ऑन-ए-डिस्टेंस हैं। (विशेष रूप से$ प्रोटोटाइप, जिसके कारण डिफ़ॉल्ट पैरामीटर संदर्भ के बजाय स्केलर संदर्भ में संबंधित पैरामीटर का मूल्यांकन किया जाता है।)

विशेष रूप से, वे सरणियों से पैरामीटर पास करना कठिन बनाते हैं। उदाहरण के लिए:

my @array = qw(a b c);

foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);

sub foo ($;$$) { print "@_\n" }

foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);

प्रिंट:

a b c
a b
a b c
3
b
a b c

3 चेतावनियों के साथ main::foo() called too early to check prototype(यदि चेतावनियाँ सक्षम हैं)। समस्या यह है कि स्केलर संदर्भ में मूल्यांकन किए गए एक सरणी (या सरणी स्लाइस) सरणी की लंबाई लौटाती है।

यदि आपको एक फ़ंक्शन लिखने की आवश्यकता है जो बिल्ट-इन की तरह काम करता है, तो एक प्रोटोटाइप का उपयोग करें। अन्यथा, प्रोटोटाइप का उपयोग न करें।

नोट: पर्ल 6 पूरी तरह से नया और बहुत उपयोगी प्रोटोटाइप होगा। यह उत्तर केवल पर्ल 5 पर लागू होता है।


लेकिन वे अभी भी एक उपयोगी जाँच प्रदान करते हैं कि आपके कॉलर और उप एक ही तर्कों का उपयोग कर रहे हैं, तो इसमें गलत क्या है?
पॉल टॉम्बलिन

2
नहीं; आम सहमति यह है कि पर्ल फ़ंक्शन प्रोटोटाइप अनिवार्य रूप से कोई लाभ नहीं प्रदान करते हैं। आप उनके साथ परेशान नहीं हो सकते हैं, कम से कम पर्ल 5 में। पर्ल 6 एक अलग (बेहतर) कहानी हो सकती है।
जोनाथन लेफ़लर

5
तर्कों को मान्य करने के बेहतर तरीके हैं, जैसे कि परमेस
friedo

10
सुधार: सरणी स्लाइसिंग एक सूची देता है , इसलिए स्केलर संदर्भ में एक सरणी टुकड़ा सूची का अंतिम तत्व देता है। आपका दूसरा टू- foo()प्रिंट प्रिंट का 2 क्योंकि आपके दो तत्व स्लाइस में अंतिम तत्व है। बदलें my @array = qw(foo bar baz)और आपको अंतर दिखाई देगा। (एक तरफ के रूप में, यही कारण है कि मैं फेंक-दूर, प्रदर्शनकारी कोड में 0- या 1-आधारित संख्यात्मक अनुक्रमों के लिए सरणियों / सूचियों को आरंभीकृत नहीं करता हूं। सूचकांकों, गणनाओं और संदर्भों के बीच भ्रम ने मुझे एक से अधिक बार काट दिया है। मूर्खतापूर्ण लेकिन सच है।)
पायलट

2
@ पिलक्रो: मैंने a b cअपनी बात को स्पष्ट करने के लिए उपयोग करने के लिए उत्तर संपादित किया ।
फ्लिम्ड

30

मैं उपरोक्त दो पोस्टरों से सहमत हूं। सामान्य तौर पर, उपयोग $से बचा जाना चाहिए। प्रोटोटाइप जब ब्लॉक तर्कों (का उपयोग कर ही उपयोगी हैं &,) globs ( *), या संदर्भ प्रोटोटाइप ( \@, \$, \%, \*)


सामान्य तौर पर, शायद, लेकिन मैं दो अपवादों का उल्लेख करना चाहूंगा: सबसे पहले, ($)प्रोटोटाइप एक नामांकित ऑपरेटर बनाता है, जो उपयोगी हो सकता है (निश्चित रूप से पर्ल उन्हें उपयोगी लगता है; मेरे पास भी अवसर है)। दूसरा, जब अंतर्निर्मित ओवरराइडिंग (आयात के माध्यम से या CORE :: GLOBAL: :) का उपयोग करते हैं, तो आपको सामान्य रूप से निर्मित प्रोटोटाइप में जो भी शामिल है, भले ही इसमें कोई भी शामिल $हो, या आप प्रोग्रामर को आश्चर्यचकित कर सकते हैं, (आप, भी) सूची के संदर्भ में जहां बिल्ट-इन अन्यथा स्केलर संदर्भ प्रदान करेगा।
सिडकिन

4

कुछ लोग, एक पर्ल सबरूटिन प्रोटोटाइप को देखते हुए, सोचते हैं कि इसका अर्थ कुछ ऐसा है जो यह नहीं करता है:

sub some_sub ($$) { ... }

पर्ल को, इसका मतलब है कि पार्सर दो तर्कों की अपेक्षा करता है। यह पर्ल का ऐसा तरीका है जिससे आप सब-इंट्रस्ट बना सकते हैं जो बिल्ट-इन की तरह व्यवहार करता है, यह सभी जानते हैं कि सफल कोड से क्या उम्मीद की जाती है। आप पर्ल्सब में प्रोटोटाइप के बारे में पढ़ सकते हैं

दस्तावेज़ीकरण को पढ़े बिना, लोग अनुमान लगाते हैं कि प्रोटोटाइप समय तर्क जाँच या कुछ इसी तरह चलाने का उल्लेख करते हैं जो उन्होंने अन्य भाषाओं में देखा है। जैसा कि ज्यादातर लोग पर्ल के बारे में अनुमान लगाते हैं, वे गलत निकलते हैं।

हालाँकि, Perl v5.20 के साथ शुरू होने पर, Perl में एक विशेषता है, जैसा कि मैं इसे लिखता हूं, यह कुछ ऐसा है जो उपयोगकर्ताओं को अपेक्षा करता है और क्या करता है। पर्ल के उप-हस्ताक्षर हस्ताक्षर समय तर्क गिनती, चर असाइन करना और डिफ़ॉल्ट सेटिंग को चलाते हैं:

use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);

animals( 'Buster', 'Nikki', 'Godzilla' );

sub animals ($cat, $dog, $lizard = 'Default reptile') { 
    say "The cat is $cat";
    say "The dog is $dog";
    say "The lizard is $lizard";
    }

यह वह सुविधा है जो आप संभवतः चाहते हैं यदि आप प्रोटोटाइप पर विचार कर रहे हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.