2017-06-12 7 views
7

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

मैं एक विधि के लिए एक एकल स्थिति पैरामीटर के साथ एक हस्ताक्षर बनाते हैं, और मुझे उम्मीद है कि यह केवल एकल स्थितित्मक तर्क स्वीकार करेगा। ,

class SomeClass { 
    method something (Int $n) { 'Ran something' } 
    } 

put SomeClass.something: 137; # Ran something 
put SomeClass.something: 137, :foo('bar'); # Ran something 

लेकिन अगर मैं एक विधि है कि एक नामित पैरामीटर लेता है परिभाषित करते हैं, कि हर बार जब मैं इसे दूसरे को परिभाषित कहा जाता है: हालांकि, यह भी नाम वाले पैरामीटर बिना किसी शिकायत के स्वीकार करता है। इसके अलावा, हालांकि मुझे लगता है कि मैं कहा है यह जरुरी है कि एक foo पैरामीटर नाम, यह आवश्यक नहीं है और यह अभी भी नाम वाले पैरामीटर है कि मैं निर्दिष्ट नहीं किया है स्वीकार करता है:

class SomeClass { 
    multi method something (Int $n) { 'Ran something' } 
    multi method something (Int $n, :$foo) { "Ran $foo" } 
    } 

put SomeClass.something: 137; # Ran 
put SomeClass.something: 137, :foo('bar'); # Ran bar 
put SomeClass.something: 137, :bar('foo'); # Ran 

तो, कुछ सवाल:

  • मैं एक हस्ताक्षर कैसे निर्दिष्ट करूं जिसमें सब कुछ शामिल है जिसे मैं स्वीकार करना चाहता हूं और बाकी सब कुछ छोड़ देता हूं?

  • मैं निकटतम मिलान हस्ताक्षर चुनने के लिए पर्ल 6 को कैसे मजबूर करूं?

  • पर्ल 6 किस तरीके से जांच करने का निर्णय लेता है?

+0

मुझे लगता है कि यह https://rt.perl.org/Ticket/Display.html?id=130920 भी –

+0

में कोई समस्या है, नहीं, यह डिज़ाइन और कार्यान्वित के रूप में काम कर रहा है, हालांकि मैं मानता हूं कि यह थोड़ा सा काउंटर- अंतर्ज्ञानी (और मुझे यह स्वीकार करना होगा कि इसे पूरी तरह से ग्रोक करने के लिए मुझे काफी समय लगा है और अभी भी यह सुनिश्चित नहीं है कि यह अधिक एलटीए होना चाहिए)। –

+0

क्या आप कुछ दस्तावेज को इंगित कर सकते हैं? –

उत्तर

1

मुझे लगता है कि Int $n, :$fooInt $n की तुलना में अधिक विशिष्ट हस्ताक्षर है। आप foo अनिवार्य

class SomeClass { 
    multi method something (Int $n,) { "Ran something" } 
    multi method something (Int $n, :$foo!) { "Ran $foo" } 
} 

या पहले हस्ताक्षर अधिक सख्त

class SomeClass { 
    multi method something (Int $n, *% where "foo" !~~ *) { "Ran something" } 
    multi method something (Int $n, :$foo) { "Ran $foo" } 
} 
10

आप चीजों है कि सबसे मुश्किल के बारे में बहु विधि प्रेषण समझ में से एक पर स्पर्श कर रहे बना सकते हैं। एहसास करने के लिए सबसे महत्वपूर्ण बात यह है कि प्रत्येकmethod हस्ताक्षर में एक निर्दिष्ट *%_ (उर्फ एक स्लर्पी हैश) है यदि कोई निर्दिष्ट नहीं है। इसका मतलब है कि यह किसी भी गैर-विशिष्ट नामित पैरामीटर खाएगा।

class A { 
    method a() { dd %_ } # %_ exists even if not specifically specified 
} 
A.a(:foo) # {:foo} 

दूसरी बात आपको पता करने की जरूरत है, जिसका नाम मापदंडों केवल गठबंधन तोड़ने वाले के रूप में कार्य करता है।

class A { 
    multi method a(:$foo) { say "foo" } 
    multi method a(:$bar) { say "bar" } 
} 
A.a(:bar) # foo 

यह प्रतीत होता है अप्रत्याशित परिणाम: तो अगर वहाँ है कि स्थितीय मापदंडों के एक ही मिलान सेट से अधिक सुझावों में कर रहे हैं, एमएमडी पहले एक है कि काम करता है (ध्यान में रखते हुए कि सभी अप्रत्याशित नाम वाले पैरामीटर %_ द्वारा slurped कर रहे हैं) का उपयोग करेगा तथ्य यह है कि के कारण होता है:

    दोनों उम्मीदवारों
  1. स्थितीय मापदंडों
  2. पहले उम्मीदवार से मेल खाता है, क्योंकि :$foo वैकल्पिक है की समान संख्या
  3. और :bar निहित *%_

द्वारा खाया जाता है इसे और अधिक की तरह आप उम्मीद, आप उम्मीदवारों के क्रम में किया जा टाई टूट की जरूरत है कि डाल करने के लिए की जरूरत है तो आप उन्हें सक्रिय करने के लिए चाहते हैं, और बनाने के काम करने के लिए अनिवार्य किसी भी नामित पैरामीटर:

class A { 
    multi method a(:$foo!) { say "foo" } 
    multi method a(:$bar!) { say "bar" } 
} 
A.a(:bar) # bar 

आप उम्मीदवारों कई नाम वाले पैरामीटर लेने हुआ है तो वो जल्दी से जटिल हो जाता है और आप संभवतः सिर्फ एक विधि %_ का आत्मनिरीक्षण का उपयोग करता है के द्वारा बेहतर कर रहे हैं:

class A { 
    method a() { 
     if %_<foo> { 
      say "foo" 
     } 
     elsif %_<bar> { 
      say "bar" 
     } 
     else { 
      die "None of the signatures matched" 
     } 
    } 
} 
A.a(:bar) # bar 

आशा इस बनाता बातें स्पष्ट :-)

+1

यदि '(: $ a, *% _)' और '(*% _)' प्रेषण के प्रयोजनों के लिए समान माना जाता है, तो यह क्यों "अस्पष्ट कॉल" त्रुटि नहीं फेंकता है जैसे कि उदाहरण के लिए '($ ए, * @ _)' बनाम '(* @ _)'? – smls

+0

क्या इसके लिए प्रलेखन है? साथ ही, यह मुझे लगता है कि मेरे पास विधियां हैं ताकि मैं उन्हें हल करना चाहूंगा, लेकिन यह किसी नामित पैरामीटर वाले कॉल के लिए काम नहीं करता है। –

5

तरीके हमेशा एक अंतर्निहित *%_ पैरामीटर के साथ आते हैं, सीएफ

say method {}.signature #=> (Mu $: *%_) 

इस विचार के साथ डिजाइन के द्वारा होता है, कि उपवर्गों तर्क वे पसंद बाहर ले सकते हैं और फिर nextsame एट अल के माध्यम से redispatch (design docs सीएफ - सुनिश्चित नहीं है कि यह कहीं और कहां दस्तावेज किया गया है)।

वहाँ अघोषित नामित तर्कों को अस्वीकार करने के कई तरीके हैं, एक जहां खंड के माध्यम से जैसे हैं

method m($positional, :$explicit, *% where !*) { ... } 

या एक खाली subsignature के माध्यम से

method m($positional, :$explicit, *%()) { ... } 

जब एक गैर घोषित तर्क गुजर, पूर्व

Constraint type check failed in binding to parameter '<anon>' 

और टी के साथ असफल हो जाएगा

Unexpected named argument '...' passed in sub-signature 

साथ वह बाद मैं दूसरों का जवाब देने के लिए multimethod प्रेषण का सही अर्थ विज्ञान छोड़ देंगे, लेकिन अंगूठे का मेरा अनुमानी शासन सुनिश्चित करें कि आवश्यक नाम वाले पैरामीटर (यानी ! मौजूद है) इस तरह के रूप में घोषित किया जाता है बनाने के लिए है और अधिक सामान्य तरीकों को अंतिम रूप देने के लिए।

+2

क्या आप इसके लिए कुछ दस्तावेज इंगित कर सकते हैं? और, शायद, इस डिजाइन में मदद क्यों करती है इसका विस्तार करें? –

+0

@briandfoy: विचार यह है कि उप-वर्ग उन तर्कों को चुन सकते हैं जिन्हें वे पसंद करते हैं और फिर 'nextsame' et al, cf [design docs] (https://design.perl6.org/S12.html#Interface_Consistency) के माध्यम से फिर से स्थानांतरित कर सकते हैं। 'Submethod BUILD' के माध्यम से निर्माण इसी तरह काम करता है। निजी तौर पर, मुझे यकीन नहीं है कि यह दृष्टिकोण अपना वजन खींच रहा है: मैंने अभी तक अपने कोड में इसका उपयोग नहीं किया है, और नकारात्मक बात यह है कि टाइपो को चुपचाप अनदेखा किया जा सकता है – Christoph

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

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