धक्का लगने के बाद स्केलर मान प्रभावित हो रहा है, या नहीं ... (रकु)


12

मुझे यह समझने में कठिनाई होती है Scalarकि धकेलने के बाद धकेलने वाले कंटेनर द्वारा रखा गया मूल्य कब और क्यों प्रभावित होता है। मैं उस समस्या को स्पष्ट करने की कोशिश करूँगा जिसे मैं दो जटिल उदाहरणों में अधिक जटिल संदर्भ में देखता था।

* उदाहरण 1 * पहले उदाहरण में, एक स्केलर $iको एक सरणी पर एक @bके भाग के रूप में धकेल दिया जाता है List। धक्का के बाद, स्केलर द्वारा आयोजित मूल्य को $i++निर्देश का उपयोग करके लूप के लिए पुनरावृत्तियों में स्पष्ट रूप से अपडेट किया गया है । इन अद्यतनों का सरणी में मान पर प्रभाव पड़ता है @b: लूप के अंत में, @b[0;0]के बराबर है 3और अब नहीं है 2

my @b;
my $i=0;
for 1..3 -> $x {
  $i++;
  say 'Loose var $i: ', $i.VAR.WHICH, " ", $i.VAR.WHERE;
  if $x == 2 {
     @b.push(($i,1));
     say 'Pushed $i   : ', @b[0;0].VAR.WHICH, " ", @b[0;0].VAR.WHERE;
  }
}
say "Post for-loop";
say "Array       : ", @b;
say 'Pushed $i   : ', @b[0;0].VAR.WHICH, " ", @b[0;0].VAR.WHERE;

आउटपुट उदाहरण 1:

Loose var $i: Scalar|94884317665520 139900170768608
Loose var $i: Scalar|94884317665520 139900170768648
Pushed $i   : Scalar|94884317665520 139900170768648
Loose var $i: Scalar|94884317665520 139900170768688
Post for-loop
Array       : [(3 1)]
Pushed $i   : Scalar|94884317665520 139900170768688

* उदाहरण 2 * दूसरे उदाहरण में, स्केलर $iलूप वेरिएबल है। हालांकि यहां तक कि $iबाद यह धक्का दे दिया गया है (अब परोक्ष बल्कि स्पष्ट रूप से), के मूल्य को अद्यतन किया जाता है $iमें सरणी @cकरता नहीं धक्का के बाद बदल; यानी लूप के बाद, यह अभी भी है 2, नहीं 3

my @c;
for 1..3 -> $i {
  say 'Loose var $i: ', $i.VAR.WHICH, " ", $i.VAR.WHERE;
  if $i == 2 {
     @c.push(($i,1));
     say 'Pushed $i   : ', @c[0;0].VAR.WHICH, " ", @c[0;0].VAR.WHERE;
  }
}
say "Post for-loop";
say "Array       : ", @c;
say 'Pushed $i   : ', @c[0;0].VAR.WHICH, " ", @c[0;0].VAR.WHERE;;

आउटपुट उदाहरण 2:

Loose var $i: Scalar|94289037186864 139683885277408
Loose var $i: Scalar|94289037186864 139683885277448
Pushed $i   : Scalar|94289037186864 139683885277448
Loose var $i: Scalar|94289037186864 139683885277488
Post for-loop
Array       : [(2 1)]
Pushed $i   : Scalar|94289037186864 139683885277448

प्रश्न: क्यों है $iमें @bजबकि, उदाहरण के 1 धक्का के बाद अद्यतन में $iमें @cउदाहरण 2 में नहीं है?

संपादित करें : @ टिमोटिमो की टिप्पणी के बाद, मैंने .WHEREउदाहरणों में आउटपुट को शामिल किया । यह (WHICH / तार्किक) स्केलर-पहचान दिखाता है $i, जबकि इसकी स्मृति पता विभिन्न लूप पुनरावृत्तियों के माध्यम से बदल जाती है। लेकिन यह स्पष्ट नहीं करता है कि उदाहरण 2 में धकेल दिया गया स्केलर एक पुराने पते ("442)" के साथ संयोजन में उसी WHICH-पहचान से बंधा हुआ है।


2
मैं आपको जवाब दे सकता हूं कि क्यों वही रहना चाहता है; कार्यान्वयन को देखें: github.com/rakudo/rakudo/blob/master/src/core.c/Scalar.pm6#L8 - यह केवल उस डिस्क्रिप्टर के उपयोग पर निर्भर करता है, जो एक छोटी सी वस्तु है, जो नाम की तरह की चीजों को रखती है चर, और प्रकार बाधा। यदि आप .WHEREइसके बजाय उपयोग करते हैं, .WHICHतो आप देख सकते हैं कि स्केलर वास्तव में लूप के चारों ओर एक अलग वस्तु है। ऐसा इसलिए होता है क्योंकि नुकीले ब्लॉकों को "कॉल" कहा जाता है, और प्रत्येक कॉल पर हस्ताक्षर "बाध्य" होता है।
टिमोटिमो

@raiph लूप के दौरान, उदाहरण 1 उदाहरण 2 के रूप में एक ही पैटर्न दिखाता है: दोनों में बदलते पते हैं। रिपोर्ट में, जो बता रहा है, मैं सहमत हूं। लेकिन अपने आप में यह स्पष्ट नहीं है कि उदाहरण 2 उदाहरण 1 के मुकाबले एक अलग अंत में क्यों आता है
18

जवाबों:


5

एक स्केलर मूल्य सिर्फ एक कंटेनर है। आप उन्हें आदिम मूल्य के बजाय एक प्रकार के स्मार्ट पॉइंटर के रूप में सोच सकते हैं।

यदि आप एक असाइनमेंट करते हैं

$foo = "something"; #or
$bar++;

आप स्केलर्स मान बदल रहे हैं, कंटेनर वही रहता है।

विचार करें

my @b; 
my $i=0; 
for 1..5 -> $x { 
  $i++; 
  @b.push(($i<>,1)); # decontainerize $i and use the bare value
} 
say @b;

तथा

my @b; 
my $i=0; 
for 1..5 -> $x { 
  $i := $i + 1;  # replaces the container with value / change value
  @b.push(($i,1)); 
} 
say @b;

जो दोनों उम्मीद के मुताबिक काम करते हैं। लेकिन: दोनों ही मामलों में, सूची में मौजूद वस्तु अब परस्पर भिन्न नहीं है, क्योंकि कोई कंटेनर नहीं है।

@b[4;0] = 99; 

इसलिए मर जाएगा। तो बस पाश चर का उपयोग करें, तो सही?

नहीं।

for 1..5 -> $x { 
  @b.push(($x,1)); # 
} 
@b[4;0] = 99; #dies

भले ही हम उत्परिवर्तित चीजों की सूची पर पुनरावृति करें।

my $one = 1;
my $two = 2;
my $three = 3;
my $four = 4;
my $five = 5;

for ($one, $two, $three, $four, $five) -> $x { 
  @b.push(($x,1)); 
} 
@b[4;0] = 99; #dies

इसलिए यहां कोई एलियासिंग नहीं है, इसके बजाय लूप वैरिएबल हमेशा एक ही कंटेनर होता है और अन्य कंटेनरों से आने वाले मानों को असाइन किया जाता है।

हम हालांकि यह कर सकते हैं।

for ($one, $two, $three, $four, $five) <-> $x { 
  @b.push(($x,1)); 
} 
@b[4;0] = 99; # works

for ($one, $two, $three, $four, $five) -> $x is rw { 
  @b.push(($x,1)); 
} 
@b[4;0] = 99; # works too

"बात" उत्परिवर्तनीय बनाने का एक तरीका एक मध्यवर्ती चर का उपयोग कर रहा है।

for 1..5 -> $x { 
  my $j = $x;
  @b.push(($j,1)); # a new container 
} 
@b[4;0] = 99;

ठीक काम करता है। या मूल संदर्भ में कम और अधिक

my @b; 
my $i=0; 
for 1..5 -> $x { 
  $i++; 
  @b.push((my $ = $i, 1)); # a new anonymous container
} 
@b[4;0] = 99;
say @b; # [(1 1) (2 1) (3 1) (4 1) (99 1)]

यह सभी देखें:

https://perl6advent.wordpress.com/2017/12/02/#theoneandonly https://docs.perl6.org/language/containers


1
इसके बजाय ($x,1), आप ऐसा भी कर सकते हैं [$x,1]जो एक नया कंटेनर (भी , BTW) के लिए पैदा करेगा1
एलिजाबेथ मैटीजेन

@ElizabethMattijsen लेकिन फिर यह एरे है जो "उठाने" को हाँ करता है?
होली

निश्चित नहीं है कि "लिफ्टिंग" से आपका क्या मतलब है, लेकिन यदि आप निर्माण पर मूल्यों को नियंत्रित करते हैं, तो हाँ।
एलिजाबेथ मैटीजेन

@ होली आपके उत्तर के लिए धन्यवाद। मुझे यकीन नहीं है कि अगर यह प्रश्न को संबोधित करता है। आपका जवाब कंटेनर की उत्परिवर्तन पर केंद्रित है, जो मुझे लगता है कि मैं समझता हूं। मुझे समझ में नहीं आ रहा है कि पहले उदाहरण में धक्का दिया गया कंटेनर $ i - या बेहतर क्यों है: इसका मूल्य - पुश के बाद अपडेट किया गया है, जबकि दूसरे उदाहरण में पुश कंटेनर का मूल्य सांख्यिकीय रूप से इस समय मूल्य से बंधा हुआ है धक्का की। पहला उदाहरण मेरे लिए कुछ मायने रखता है (कंटेनर पॉइंटर टू Intऑब्जेक्ट है -> Intलूप के लिए प्रतिस्थापित हो जाता है -> कंटेनर पॉइंट टू न्यू Int), लेकिन दूसरा ऐसा नहीं करता है।
ozzy

@ होली मैं प्रश्न को स्पष्ट करने का प्रयास करूँगा।
ozzy

3

कुछ समय के लिए मेरे उपरोक्त प्रश्न के साथ खेलने और सोचने के बाद, मैं एक उत्तर दूंगा ... यह मेरी ओर से शुद्ध अनुमान है, इसलिए कृपया यह कहने के लिए स्वतंत्र महसूस करें कि यह गैर-समझदार है, और यदि आप जानते हैं, तो क्यों...

पहले उदाहरण में, $iलूप के लेक्सिकल दायरे के बाहर परिभाषित किया गया है। नतीजतन, $iलूप और इसके पुनरावृत्तियों से स्वतंत्र मौजूद है। जब $iलूप के अंदर से संदर्भित किया जाता है, तो केवल एक ही होता है $iजो प्रभावित हो सकता है। यह वह है $iजिसे धक्का दिया जाता है @b, और इसकी सामग्री को बाद में लूप में संशोधित किया जाता है।

दूसरे उदाहरण में, $iलूप के लेक्सिकल दायरे के अंदर परिभाषित किया गया है। जैसा कि @timotimo ने बताया, इंगित खंड को प्रत्येक पुनरावृत्ति के लिए कहा जाता है, जैसे कि सबरूटीन; $iइसलिए प्रत्येक पुनरावृत्ति के लिए नए सिरे से घोषित किया जाता है, और संबंधित ब्लॉक में पहुंचा दिया जाता है। जब $iलूप के अंदर संदर्भित किया जाता है, तो संदर्भ ब्लॉक-इटरेशन-विशिष्ट के लिए होता है $i, जो सामान्य रूप से संबंधित लूप चलना समाप्त होने पर मौजूद नहीं रहेगा। लेकिन क्योंकि कुछ बिंदु $iपर धकेल दिया जाता है @c, खंड-पुनरावृत्ति-विशिष्ट $iहोल्डिंग मान 2का संदर्भ पुनरावृत्ति की समाप्ति के बाद कचरा कलेक्टर द्वारा हटाया नहीं जा सकता है। यह अस्तित्व में रहेगा ..., लेकिन फिर भी $iबाद के पुनरावृत्तियों से अलग होगा ।


@raiph धन्यवाद वह में स्वयं कर लूँगा। शायद कि खुद से अधिक अंतर्दृष्टि वाला कोई व्यक्ति जवाब को ठीक से दे सकता है। मैं किसी भी तरह से अपने स्वयं के उत्तर को तब तक सही नहीं मानूंगा जब तक कि इसकी पुष्टि (या सुधार) उन लोगों द्वारा नहीं की जाती है जो जानते हैं (बल्कि अनुमान की तरह, अपने आप को)।
ozzy
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.