ค่าสเกลาร์ได้รับผลกระทบหลังจากกดหรือไม่… (Raku)


12

ฉันมีปัญหาในการทำความเข้าใจว่าเมื่อใดและเพราะเหตุใดค่าที่จัดขึ้นโดยScalarคอนเทนเนอร์ที่ถูกพุชได้รับผลกระทบหลังจากการพุช ฉันจะพยายามอธิบายปัญหาที่ฉันพบในบริบทที่ซับซ้อนมากขึ้นในตัวอย่างสองตัวอย่าง

* * * * * * * * ตัวอย่างที่ 1ในตัวอย่างแรกเป็นสเกลา$iถูกผลักลงบนอาร์เรย์เป็นส่วนหนึ่งของ@b Listหลังจากการพุชค่าที่เก็บโดยสเกลาร์จะได้รับการอัพเดตอย่างชัดเจนในการวนซ้ำในภายหลังของ for for loop โดยใช้$i++คำสั่ง การปรับปรุงเหล่านี้มีผลกระทบต่อค่าในอาร์เรย์@b: ในตอนท้ายของสำหรับวงที่@b[0;0]มีค่าเท่ากับและไม่มีอีกต่อไปเพื่อ32

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จะไม่เปลี่ยนแปลงหลังจากการพุช คือหลังจากที่สำหรับวงก็ยังคงไม่ได้23

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 ไม่ได้?

แก้ไข : ตามความคิดเห็นของ @ timotimo ฉันรวมเอาท์พุทของ.WHEREในตัวอย่าง สิ่งนี้แสดงให้เห็นถึงสเกลาร์ (ซึ่ง / โลจิคัล) เอกลักษณ์ของสเกลาร์$iยังคงเหมือนเดิมในขณะที่ที่อยู่หน่วยความจำของมันเปลี่ยนแปลงผ่านการวนซ้ำลูปต่าง ๆ แต่มันไม่ได้อธิบายว่าทำไมในตัวอย่างที่ 2 สเกลาร์ที่ถูกผลักยังคงเชื่อมโยงกับเอกลักษณ์ WHICH- ตัวตนเดียวกันรวมกับที่อยู่เดิม ("448)


2
ฉันสามารถให้คำตอบกับคุณว่าทำไมซึ่งดูเหมือนจะยังคงเหมือนเดิม; ดูการใช้งาน: github.com/rakudo/rakudo/blob/master/src/core.c/Scalar.pm6#L8 - ขึ้นอยู่กับ descriptor ที่ใช้ซึ่งเป็นวัตถุเล็ก ๆ ที่เก็บสิ่งต่าง ๆ เช่นชื่อของ ตัวแปรและข้อ จำกัด ประเภท ถ้าคุณใช้.WHEREแทนคุณ.WHICHจะเห็นว่าสเกลาร์เป็นวัตถุที่แตกต่างกันในแต่ละครั้งที่วนรอบ ที่เกิดขึ้นเพราะบล็อกแหลมเป็น "เรียกว่า" และลายเซ็นคือ "ผูกพัน" ในการโทรแต่ละครั้ง
timotimo

@raiph ในระหว่างลูปตัวอย่างที่ 1 แสดงรูปแบบเดียวกับตัวอย่างที่ 2: ทั้งคู่มีการเปลี่ยนที่อยู่ที่รายงานโดย. WHERE ที่บอกว่าฉันเห็นด้วย แต่ในตัวมันเองมันไม่ได้อธิบายว่าทำไมตัวอย่างที่ 2 ถึงจุดจบที่แตกต่างจากตัวอย่างที่ 1
ozzy

คำตอบ:


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]ซึ่งจะสร้างคอนเทนเนอร์ใหม่ (ยัง1, BTW)
เอลิซาเบ Mattijsen

@ElizabethMattijsen แต่แล้วอาเรย์ที่ "ยก" ใช่ไหม?
Holli

ไม่แน่ใจว่าคุณหมายถึงอะไรโดย "การยก" แต่ถ้าคุณกำหนดค่าให้กับการสร้างจริงแล้วใช่
Elizabeth Mattijsen

@Holli ขอบคุณสำหรับการตอบกลับของคุณ ฉันไม่แน่ใจว่ามันตอบคำถาม คำตอบของคุณมุ่งเน้นไปที่ความไม่แน่นอนของภาชนะบรรจุซึ่งฉันคิดว่าฉันเข้าใจ สิ่งที่ฉันไม่เข้าใจคือเหตุผลว่าทำไมในตัวอย่างแรกภาชนะผลักดัน $ i - หรือดีกว่า: ค่าของมัน - ได้รับการปรับปรุงหลังจากการผลักในขณะที่ในตัวอย่างที่สองมูลค่าของภาชนะที่บรรจุยังคงผูกติดกับค่าในปัจจุบัน ของการผลักดัน ตัวอย่างแรกมีเหตุผลบางอย่างสำหรับฉัน (คอนเทนเนอร์คือตัวชี้ไปยังIntวัตถุ -> Intถูกแทนที่ด้วยสำหรับลูป -> คอนเทนเนอร์ชี้ไปที่ใหม่Int) แต่สิ่งที่สองไม่ได้
ozzy

@Holli ฉันจะพยายามชี้แจงคำถาม
ozzy

3

หลังจากเล่นด้วยและคิดเกี่ยวกับคำถามข้างต้นบางครั้งฉันจะเล่นคำตอบ ... มันเป็นการคาดเดาที่บริสุทธิ์ในส่วนของฉันดังนั้นโปรดอย่าลังเลที่จะบอกว่ามันไม่สมเหตุสมผลถ้าเป็นและถ้าคุณรู้ ทำไม...

ในตัวอย่างแรก$iถูกกำหนดไว้นอกขอบเขตของคำของ for for loop ดังนั้นจึง$iมีความเป็นอิสระจากการวนซ้ำและการวนซ้ำ เมื่อ$iมีการอ้างอิงจากภายในวงมีเพียงคนเดียว$iที่สามารถได้รับผลกระทบ มันคือสิ่งนี้$iที่ถูกผลักเข้าไป@bและมีการดัดแปลงเนื้อหาหลังจากนั้นในลูป

ในตัวอย่างที่สอง$iมีการกำหนดไว้ภายในขอบเขตคำศัพท์ของ for for loop เมื่อ @timotimo ชี้ให้เห็นการบล็อกของแหลมถูกเรียกสำหรับการวนซ้ำแต่ละครั้งเช่นรูทีนย่อย $iดังนั้นจะประกาศใหม่สำหรับการวนซ้ำแต่ละครั้งและกำหนดขอบเขตไปยังบล็อกที่เกี่ยวข้อง เมื่อ$iมีการอ้างอิงภายในลูปการอ้างอิงคือไปยังบล็อกการทำซ้ำเฉพาะ$iซึ่งโดยปกติจะหยุดอยู่เมื่อการวนซ้ำลูปที่เกี่ยวข้องสิ้นสุดลง แต่เนื่องจากในบางจุด$iจะถูกผลักไป@cอ้างอิงถึงบล็อกย้ำเฉพาะ$iมูลค่าการถือครอง2ไม่สามารถลบได้โดยการเก็บขยะหลังจากการสิ้นสุดของการทำซ้ำ มันจะยังคงอยู่ ... แต่ยังคงแตกต่างจาก$iการทำซ้ำในภายหลัง


@raiph ขอบคุณ ฉันจะทำอย่างนั้น. บางทีคนที่มีความเข้าใจลึกซึ้งกว่าตัวเองก็สามารถตอบคำถามได้อย่างเหมาะสม ฉันจะไม่ยอมรับคำตอบของฉันว่าถูกต้องจนกว่าจะได้รับการยืนยัน (หรือปรับปรุง) โดยผู้รู้ (แทนที่จะเดาเหมือนตัวฉันเอง)
ozzy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.