Skaler değer itme sonrasında etkilenir ya da etkilenmez… (Raku)


12

İtilen bir Scalarkonteyner tarafından tutulan değerin itme sonrasında ne zaman ve neden etkilendiğini anlamakta güçlük çekiyorum . Daha karmaşık bir bağlamda karşılaştığım sorunu iki stilize örnekte göstermeye çalışacağım.

* Örnek 1 * İlk örnekte, bir skaler a'nın $ibir @bparçası olarak bir diziye itilir List. Zorlamadan sonra, skaler tarafından tutulan değer, $i++talimatı kullanarak for döngüsünün sonraki yinelemelerinde açıkça güncellenir . Bu güncellemeler dizideki değer üzerinde bir etkiye sahiptir @b: for döngüsünün sonunda @b[0;0], eşittir 3ve artık değil 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;

Çıktı örneği 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

* Örnek 2 * İkinci örnekte, skaler $idöngü değişkenidir. Olsa $ida, (örtük yerine açıkça daha şimdi) değerini basıldıktan sonra güncellenir $idizisi içinde @cyok değil itme sonra değişmez; yani for döngüsünden sonra, hala 2değil 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;;

Çıktı örneği 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

Soru: Neden $iiçinde @biken, itme sonra güncellenir örnek 1'de $ide @cörnek 2'de değil mi?

edit : @ timotimo'nun yorumunu takiben .WHERE, örneklerin çıktısını dahil ettim . Bu, $ibellek adresi çeşitli döngü yinelemelerinde değişirken , (WHICH / mantıksal) skaler kimliğinin aynı kaldığını gösterir. Ancak, örnek 2'de itilen skalerin neden eski bir adresle birlikte aynı WHICH kimliğine bağlı kaldığını açıklamamaktadır ("448).


2
size HANGİ aynı kalıyor gibi cevap verebilirim; uygulamaya bakın: github.com/rakudo/rakudo/blob/master/src/core.c/Scalar.pm6#L8 - sadece kullanılan tanımlayıcıya bağlıdır, bu da adı gibi şeyleri tutan küçük bir nesnedir. değişken ve tür kısıtı. .WHEREbunun yerine kullanırsanız .WHICH, skalanın döngü etrafında her seferinde aslında farklı bir nesne olduğunu görebilirsiniz. Bunun nedeni, sivri blokların "çağrılması" ve her çağrıda imza "bağlanması" nedeniyle olur.
timotimo

@raiph Döngü sırasında, Örnek 1, Örnek 2 ile aynı modeli gösterir: her ikisinde de .WHERE tarafından bildirilen değişen adresler vardır; Ancak kendi içinde, Örnek 2'nin neden Örnek 1'den farklı bir sona geldiğini açıklamıyor
ozzy

Yanıtlar:


5

Skaler değer sadece bir kaptır. Onları ilkel bir değerden ziyade bir tür akıllı işaretçi olarak düşünebilirsiniz.

Bir ödev yaparsanız

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

skaler değerini değiştiriyorsanız, kap aynı kalır.

Düşünmek

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

ve

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;

Her ikisi de beklendiği gibi çalışıyor. Ancak: Her iki durumda da listedeki şey artık değiştirilemez, çünkü konteyner yok.

@b[4;0] = 99; 

bu yüzden ölecek. Öyleyse sadece döngü değişkenini kullanın, değil mi?

Hayır.

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

Değişken şeylerin bir listesini tekrarlasak bile.

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

Yani burada bir örtüşme olmaz, bunun yerine döngü değişkeni her zaman aynı kaptır ve diğer kaplardan gelen değerleri alır.

Bunu yine de yapabiliriz.

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

"Şey" değişken kılmanın bir yolu, bir ara değişken kullanmaktır.

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

iyi çalışıyor. Veya orijinal bağlamda daha kısa ve daha fazlası

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)]

Ayrıca bakınız:

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


1
Yerine ($x,1), aynı zamanda yapabileceği [$x,1]hangi olurdu (ayrıca yeni bir kapsayıcı oluşturmak 1BTW,)
Elizabeth Mattijsen

@ElizabethMattijsen Ama o zaman "kaldırma" yapan Dizi var mı?
Holli

"Kaldırmak" ile ne demek istediğinizden emin değilim, ama yaratılıştaki değerleri kapsayıyorsanız, evet.
Elizabeth Mattijsen

@Holli Cevabınız için teşekkürler. Soruyu ele alıp almadığından emin değilim. Cevabınız, anladığımı düşündüğüm kabın değişebilirliğine odaklanıyor. Anlamadığım şey, ilk örnekte itilen kapsayıcı neden $ i - veya daha iyisi: değerinin - itmeden sonra güncellenirken, ikinci örnekte itilen kapsayıcı değerinin şu anda değere statik olarak bağlı kalmasıdır itme. İlk örnek bana bir anlam ifade ediyor (kap Intnesneye işaretçi -> Intdöngü için değiştiriliyor -> kap yeni işaret ediyor Int), ancak ikincisi anlamıyor.
ozzy

@Holli Soruyu açıklığa kavuşturmaya çalışacağım.
ozzy

3

Yukarıdaki sorumla bir süre oynadıktan ve bir süre düşündükten sonra, bir cevap oynayacağım ... Bu benim için saf bir varsayımdır, bu yüzden lütfen bunun mantıklı olmadığını ve eğer biliyorsan, neden...

İlk örnekte, $ifor döngüsünün sözcüksel kapsamı dışında tanımlanmıştır. Sonuç olarak, $idöngü ve yinelemelerinden bağımsız olarak bulunur. Ne zaman $idöngü içinden başvuruda bulunulan, sadece bir tane $ietkilenebilir. Bu, $iiçine itilen @bve daha sonra içeriğini döngüde değiştiren şeydir .

İkinci örnekte, $ifor döngüsünün sözcüksel kapsamı içinde tanımlanmıştır. @Timotimo'nun işaret ettiği gibi, sivri blok bir altyordam gibi her bir yineleme için çağrılır; $ibu nedenle her bir yineleme için taze olarak bildirilir ve ilgili bloğa dahil edilir. $iDöngü içinde referans alındığında , referans, blok döngü yinelemesine özgüdür $ive normalde ilgili döngü yinelemesi sona erdiğinde var olmaya son bulur. Ancak bir noktaya $iitildiği için @c, blok yinelemeye özgü $itutma değerine yapılan referans 2, yinelemenin sona ermesinden sonra çöp toplayıcı tarafından silinemez. Var olmaya devam edecek ... ama yine de $isonraki iterasyonlardan farklı olacak .


@raiph Teşekkürler. Bunu yapacağım. Belki de benden daha fazla kavrayışa sahip biri cevabı düzgün bir şekilde (yeniden) ifade edebilir. Kendi cevabımı bilenler tarafından (benim gibi tahmin etmek yerine) onaylayana kadar (veya geliştirilene kadar) doğru olarak kabul etmeyeceğim.
ozzy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.