रकु में निजी और सार्वजनिक विशेषताओं और अभिगमकों को मिलाना


12
#Private attribute example
class C { 
    has $!w;                            #private attribute
    multi method w { $!w }              #getter method
    multi method w ( $_ ) {                 #setter method
        warn “Don’t go changing my w!”;   #some side action
        $!w = $_
    }  
}
my $c = C.new
$c.w( 42 )
say $c.w #prints 42
$c.w: 43
say $c.w #prints 43

#but not
$c.w = 44
Cannot modify an immutable Int (43)

अब तक, इतना उचित है, और फिर

#Public attribute example
class C { 
    has $.v is rw    #public attribute with automatic accessors
}
my $c = C.new
$c.v = 42
say $c.v #prints 42

#but not
$c.v( 43 ) #or $c.v: 43
Too many positionals passed; expected 1 argument but got 2

मुझे '=' असाइनमेंट की immediacy पसंद है, लेकिन मुझे साइड एक्ट्स में बिंग करने में आसानी की जरूरत है जो मल्टी मेथड प्रदान करते हैं। मैं समझता हूं कि ये दो अलग-अलग दुनिया हैं, और यह कि वे मिश्रण नहीं करते हैं।

लेकिन - मुझे समझ नहीं आ रहा है कि मैं सिर्फ $ cv (43) क्यों नहीं जा सकता

  1. मुझे लगता है कि रक्कू मुझे इन दो तरीकों का मिश्रण नहीं करने के लिए मार्गदर्शन कर रहे हैं - कुछ निजी और कुछ सार्वजनिक विशेषताओं और यह दबाव विधि विधि (कुछ के साथ: बृहदान्त्र से चीनी) की ओर है - क्या यह रकु के डिजाइन का इरादा है?
  2. क्या मैं कुछ भूल रहा हूँ?

आप एक प्रॉक्सी
user0721090601

आप एक प्रॉक्सी का उपयोग कैसे कर सकते हैं? मेरा मतलब है, एक्सेसर पहले से ही एक कंटेनर लौटाता है जब is rwनिर्दिष्ट किया जाता है। एक प्रॉक्सी लौटाकर एक्सेसर पर स्वीकार्य मापदंडों की संख्या को बदलने नहीं जा रहा है।
एलिजाबेथ मैटीजसेन

@ElizabethMattijsen शायद मैंने इस सवाल को गलत समझा। लेकिन ऐसा लगता है कि वह जो चाहता है उसके लिए काम करता है (दोनों को सक्षम करने = fooऔर .(foo)सेटिंग के लिए) और दोनों मामलों में होने वाले दुष्प्रभावों को सक्षम करने के लिए (लेकिन केवल तब ही नहीं): tio.run/…
user0721090601

जवाबों:


13

क्या यह राकू के डिजाइन का इरादा है?

यह कहना उचित है कि Raku इस क्षेत्र में पूरी तरह से अनधिकृत नहीं है। आपका प्रश्न रक्कू के डिजाइन में दो विषयों को छूता है, जो दोनों थोड़ी चर्चा के लायक हैं।

Raku में प्रथम श्रेणी के एल-मान हैं

Raku प्रथम श्रेणी की चीज होने के कारण l-मानों का भरपूर उपयोग करता है। जब हम लिखते हैं:

has $.x is rw;

उत्पन्न विधि है:

method x() is rw { $!x }

is rwयहाँ इंगित करता है कि विधि एक लौटा रहा है l-मूल्य - यह है कि, कुछ ऐसा है जो करने के लिए सौंपा जा सकता है। इस प्रकार जब हम लिखते हैं:

$obj.x = 42;

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

my $target := $obj.x;
$target = 42;

ऑब्जेक्ट विशेषता को असाइन करना होगा। सूची असाइनमेंट सहित कई अन्य सुविधाओं के पीछे भी यही तंत्र है। उदाहरण के लिए, यह:

($x, $y) = "foo", "bar";

एक का निर्माण करके काम करता है Listकंटेनर युक्त $xऔर $y, और फिर इस मामले में असाइनमेंट ऑपरेटर काम करने के लिए प्रत्येक पक्ष जोड़ो में iterates। इसका मतलब है कि हम rwवहां ऑब्जेक्ट एक्सेसर्स का उपयोग कर सकते हैं :

($obj.x, $obj.y) = "foo", "bar";

और यह सब स्वाभाविक रूप से काम करता है। ऐरे और हैश के स्लाइस को असाइन करने के पीछे भी यही तंत्र है।

एक Proxyएल-मूल्य कंटेनर बनाने के लिए भी उपयोग कर सकते हैं जहां इसे पढ़ने और लिखने का व्यवहार आपके नियंत्रण में है। इस प्रकार, आप साइड-एक्शन डाल सकते हैं STORE। तथापि...

Raku "बसने" पर सिमेंटिक तरीकों को प्रोत्साहित करता है

जब हम OO का वर्णन करते हैं, तो "एनकैप्सुलेशन" और "डेटा हाइडिंग" जैसे शब्द अक्सर सामने आते हैं। यहां मुख्य विचार यह है कि वस्तु के अंदर स्थित राज्य मॉडल - अर्थात, जिस तरह से वह डेटा का प्रतिनिधित्व करने के लिए चुनता है, उसे अपने व्यवहारों (विधियों) को लागू करने के लिए - विकसित करने के लिए स्वतंत्र है, उदाहरण के लिए नई आवश्यकताओं को संभालने के लिए। वस्तु जितनी जटिल होती है, उतनी ही मुक्त होती है।

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

उस ने कहा, classवास्तव में रिकॉर्ड / उत्पाद प्रकार के कई उपयोग हैं: वे केवल डेटा आइटम का एक समूह के साथ समूह के लिए मौजूद हैं। यह कोई दुर्घटना नहीं है कि .सतर्क केवल एक सहायक उत्पन्न नहीं करता है, बल्कि:

  • डिफ़ॉल्ट ऑब्जेक्ट आरंभीकरण तर्क (जो है, के class Point { has $.x; has $.y; }रूप में त्वरित किया जा सकता है Point.new(x => 1, y => 2)) द्वारा निर्धारित किया जा रहा है , और .rakuडंपिंग विधि में भी प्रदान करता है कि विशेषता को खोलता है।
  • विशेषता को डिफ़ॉल्ट .Captureऑब्जेक्ट में बदल देता है, जिसका अर्थ है कि हम इसे विनाशकारी (जैसे sub translated(Point (:$x, :$y)) { ... }) में उपयोग कर सकते हैं ।

यदि आप एक और अधिक प्रक्रियात्मक या कार्यात्मक शैली में लिख रहे थे और classरिकॉर्ड प्रकार को परिभाषित करने के लिए एक साधन के रूप में उपयोग कर रहे थे, तो आप क्या चाहते हैं ।

Raku डिजाइन बसने में चालाक चीजों को करने के लिए अनुकूलित नहीं है, क्योंकि यह एक खराब चीज माना जाता है जिसके लिए अनुकूलन करना है। यह एक रिकॉर्ड प्रकार के लिए आवश्यक है से परे है; कुछ भाषाओं में हम तर्क दे सकते हैं कि जो कुछ सौंपा जा रहा है, उसका सत्यापन हम करना चाहते हैं, लेकिन Raku में हम उसके लिए subsetटाइप कर सकते हैं । उसी समय, यदि हम वास्तव में एक OO डिजाइन कर रहे हैं, तो हम सार्थक व्यवहार की एक एपीआई चाहते हैं जो राज्य मॉडल को छुपाता है, बल्कि गेटर्स / सेटर के संदर्भ में सोचता है, जो कॉलोकेट करने में विफलता का कारण बनता है डेटा और व्यवहार, जो कि वैसे भी OO करने की बात है।


Proxyएस को चेतावनी देने पर अच्छी बात (भले ही मैंने यह सुझाव दिया हो)। केवल एक बार मैंने उन्हें बहुत उपयोगी पाया है LanguageTag। आंतरिक रूप से, $tag.regionप्रकार का ऑब्जेक्ट देता है Region(क्योंकि यह आंतरिक रूप से संग्रह किया गया है), लेकिन वास्तविकता यह है कि यह असीम अधिक सुविधाजनक है लोगों का कहना है के लिए $tag.region = "JP"खत्म हो गया $tag.region.code = "JP"। और यह वास्तव में केवल अस्थायी है जब तक कि मैं Strप्रकार से एक जबरदस्ती व्यक्त नहीं कर सकता , उदाहरण के लिए, has Region(Str) $.region is rw(जो दो अलग-अलग नियोजित लेकिन कम प्राथमिकता वाली सुविधाओं की आवश्यकता है)
user0721090601

धन्यवाद @ @ रतनथन को डिज़ाइन का समय निकालने के लिए समय देने के लिए - मुझे कुछ प्रकार के तेल और पानी के पहलू पर संदेह था और मेरे जैसे गैर सीएस के लिए, मुझे वास्तव में छिपे हुए राज्य के साथ उचित OO और वर्ग के आवेदन के बीच अंतर मिलता है। गूढ़ डेटा धारकों के निर्माण के लिए एक मैत्रीपूर्ण तरीका जो C ++ में पीएचडी लेगा। और प्रॉक्सी 0 पर आपके विचारों के लिए user072 ...। मुझे पहले से ही प्रॉक्सी के बारे में पता था, लेकिन संदेह था कि वे (और / या लक्षण) जानबूझकर तेल और पानी के मिश्रण को हतोत्साहित करने के लिए काफी
खतरनाक सिंटैक्स हैं

p6steve: Raku वास्तव में सबसे आम / आसान चीजों को सुपर आसान बनाने के लिए डिज़ाइन किया गया था। जब आप सामान्य मॉडल से विचलित होते हैं, तो यह हमेशा संभव होता है (मुझे लगता है कि आपने तीन अलग-अलग तरीकों के बारे में देखा है जो आप अभी तक चाहते हैं ... और वहाँ निश्चित रूप से अधिक है), लेकिन यह आपको थोड़ा काम करता है - बस बनाने के लिए पर्याप्त है सुनिश्चित करें कि आप जो कर रहे हैं वह वास्तव में आप चाहते हैं। लेकिन लक्षण, परदे के पीछे, कठबोली, आदि के माध्यम से, आप इसे बना सकते हैं, इसलिए आपको केवल कुछ अतिरिक्त पात्रों की आवश्यकता होती है जब आपको इसकी आवश्यकता होती है।
user0721090601

7

लेकिन - मुझे समझ नहीं आ रहा है कि मैं सिर्फ $ cv (43) क्यों नहीं जा सकता

खैर, यह वास्तव में आर्किटेक्ट तक है। लेकिन गंभीरता से, नहीं, यह केवल मानक तरीके से काम नहीं करता है।

अब, Attributeमॉड्यूल स्पेस में एक विशेषता बनाना पूरी तरह से संभव होगा , कुछ ऐसा is settable, जो एक वैकल्पिक एक्सेसर विधि का निर्माण करेगा जो मान सेट करने के लिए एकल मान स्वीकार करेगा । कोर में ऐसा करने के साथ समस्या यह है कि क्या मुझे लगता है कि इस तरह के म्यूटेटर के वापसी मूल्य के बारे में दुनिया में मूल रूप से 2 शिविर हैं: क्या यह नए मूल्य, या पुराने मूल्य को लौटाएगा ?

कृपया मुझसे संपर्क करें यदि आप मॉड्यूल अंतरिक्ष में इस तरह के एक लक्षण को लागू करने में रुचि रखते हैं।


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

6

मुझे वर्तमान में संदेह है कि आप भ्रमित हो गए हैं। 1 इससे पहले कि मैं उस पर स्पर्श करता हूं, चलो शुरू करें कि आप किस बारे में भ्रमित नहीं हैं:

मुझे =असाइनमेंट की immediacy पसंद है , लेकिन मुझे साइड एक्ट्स में बिंग करने में आसानी की आवश्यकता है जो मल्टी मेथड प्रदान करते हैं। ... मुझे समझ नहीं आता कि मैं सिर्फ $c.v( 43 )सार्वजनिक विशेषता सेट करने के लिए क्यों नहीं जा सकता

आप इन सभी चीजों को कर सकते हैं। यह कहना है कि आप =असाइनमेंट, और बहु ​​विधियों का उपयोग करते हैं, और "बस जाओ $c.v( 43 )", सभी एक ही समय में यदि आप चाहते हैं:

class C {
  has $!v;
  multi method v                is rw {                  $!v }
  multi method v ( :$trace! )   is rw { say 'trace';     $!v }
  multi method v ( $new-value )       { say 'new-value'; $!v = $new-value }
}
my $c = C.new;
$c.v = 41;
say $c.v;            # 41
$c.v(:trace) = 42;   # trace
say $c.v;            # 42
$c.v(43);            # new-value
say $c.v;            # 43

भ्रम का एक संभावित स्रोत 1

पर्दे के पीछे, has $.foo is rwकी तर्ज पर एक विशेषता और एक एकल विधि उत्पन्न करता है:

has $!foo;
method foo () is rw { $!foo }

हालांकि ऊपर बहुत सही नहीं है। हमारे द्वारा देखे जा रहे व्यवहार को देखते हुए, कंपाइलर की ऑटोजेनरेटेड fooविधि को किसी तरह से इस तरह से घोषित किया जा रहा है कि उसी नाम की कोई भी नई विधि उसे चुपचाप छाया दे। 2

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

फुटनोट

1 निजी बनाम सार्वजनिक गेटर्स / सेटर के बारे में राकु की राय के बारे में स्पष्ट, पूरी तरह से, आधिकारिक लेखांकन के लिए jnthn का जवाब देखें और जब आप सार्वजनिक गेटर्स / सेटर की घोषणा करते हैं, तो इसका मतलब क्या होता है has $.foo

2 यदि किसी विशेषता के लिए एक ऑटोजेनरेटेड एक्सेसर विधि घोषित की गई थी only, तो राकू, मैं यह मान सकता हूं कि यदि एक ही नाम के साथ एक विधि घोषित की गई थी , तो एक अपवाद को फेंक दें। यदि यह घोषित किया गया था multi, तो इसे छायांकित नहीं किया जाना चाहिए यदि नई विधि भी घोषित की गई थी multi, और यदि नहीं तो एक अपवाद फेंक देना चाहिए। तो ऑटोजेनरेटेड एक्सेसर को न तो onlyऔर न ही multiइसके बजाय किसी तरह से घोषित किया जा रहा है जो मूक छायांकन की अनुमति देता है।


अहा - थैंक्स @raiph - यही वह चीज है जो मुझे लगा कि गायब है। अब समझ में आता है। प्रति Jnthn मैं शायद एक बेहतर सच्चे OO कोडर बनने की कोशिश करूंगा और शुद्ध डेटा कंटेनरों के लिए सेटर शैली रखूंगा। लेकिन यह जानना अच्छा है कि यह टूलबॉक्स में है!
p6steve
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.