Saya mengalami kesulitan memahami kapan dan mengapa nilai yang dipegang oleh Scalar
wadah terdorong dipengaruhi setelah dorongan. Saya akan mencoba mengilustrasikan masalah yang saya hadapi dalam konteks yang lebih rumit dalam dua contoh bergaya.
* Contoh 1 * Dalam contoh pertama, skalar $i
didorong ke array @b
sebagai bagian dari a List
. Setelah push, nilai yang dimiliki oleh skalar secara eksplisit diperbarui dalam iterasi selanjutnya dari for loop menggunakan $i++
instruksi. Pembaruan ini memiliki efek pada nilai dalam array @b
: pada akhir loop for, @b[0;0]
sama dengan 3
, dan tidak lagi 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;
Contoh output 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
* Contoh 2 * Dalam contoh kedua, skalar $i
adalah variabel loop. Meskipun $i
diperbarui setelah telah mendorong (sekarang secara implisit bukan eksplisit), nilai $i
dalam array @c
tidak tidak
berubah setelah push; yaitu setelah for loop, masih 2
, tidak 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;;
Contoh output 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
Pertanyaan: Mengapa $i
di @b
dalam contoh 1 diperbarui setelah push, sementara $i
di @c
dalam contoh 2 tidak?
sunting : Mengikuti komentar @ timotimo, saya memasukkan output dari .WHERE
dalam contoh. Ini menunjukkan skalar-identitas (WHICH / logis) $i
tetap sama, sementara alamat memorinya berubah melalui berbagai iterasi loop. Tetapi itu tidak menjelaskan mengapa dalam contoh 2 skalar yang didorong tetap terikat pada identitas WHICH yang sama dalam kombinasi dengan alamat lama ("448).
sumber
.WHERE
alih-alih,.WHICH
Anda dapat melihat bahwa skalar sebenarnya adalah objek yang berbeda setiap kali di loop. Itu terjadi karena blok runcing "disebut", dan tanda tangan "terikat" pada setiap panggilan.Jawaban:
Nilai skalar hanyalah sebuah wadah. Anda dapat menganggap mereka sebagai semacam penunjuk pintar, bukan nilai primitif.
Jika Anda melakukan tugas
Anda mengubah nilai skalar, wadah tetap sama.
Mempertimbangkan
dan
Keduanya berfungsi seperti yang diharapkan. Tetapi: Dalam kedua kasus, benda dalam daftar tidak dapat berubah lagi, karena tidak ada wadah.
karena itu akan mati. Jadi gunakan saja variabel loop, kan?
Tidak.
bahkan jika kita beralih pada daftar hal-hal yang bisa berubah.
Jadi tidak ada alias yang terjadi di sini, sebaliknya variabel loop selalu wadah yang sama dan mendapatkan nilai yang ditetapkan yang berasal dari wadah lain.
Kita bisa melakukan ini.
Cara untuk membuat "hal" bisa berubah menggunakan variabel perantara.
bekerja dengan baik. Atau lebih pendek dan lebih banyak dalam konteks aslinya
Lihat juga:
https://perl6advent.wordpress.com/2017/12/02/#theoneandonly https://docs.perl6.org/language/containers
sumber
($x,1)
, Anda juga bisa melakukan[$x,1]
yang akan membuat wadah baru (juga untuk1
, BTW)Int
objek ->Int
diganti untuk loop -> container menunjuk ke yang baruInt
), tetapi yang kedua tidak.Setelah bermain dengan dan memikirkan pertanyaan saya di atas untuk beberapa waktu, saya akan bertaruh jawaban ... Ini dugaan murni di pihak saya, jadi jangan ragu untuk mengatakan itu tidak masuk akal jika itu, dan jika Anda kebetulan tahu, Mengapa...
Pada contoh pertama,
$i
didefinisikan di luar lingkup leksikal for for. Akibatnya,$i
ada independen dari loop dan iterasinya. Ketika$i
direferensikan dari dalam loop, hanya ada satu$i
yang bisa terpengaruh. Inilah$i
yang didorong ke dalam@b
, dan isinya dimodifikasi setelah itu dalam loop.Pada contoh kedua,
$i
didefinisikan di dalam lingkup leksikal for for. Seperti @timotimo tunjukkan, blok runcing dipanggil untuk setiap iterasi, seperti subrutin;$i
Oleh karena itu baru dinyatakan untuk setiap iterasi, dan dicakup dalam blok masing-masing. Ketika$i
direferensikan di dalam loop, referensi adalah untuk blok-iterasi-spesifik$i
, yang biasanya tidak ada ketika iterasi loop masing-masing berakhir. Tetapi karena pada titik tertentu$i
didorong ke@c
, referensi ke$i
nilai holding spesifik blok-iterasi2
tidak dapat dihapus oleh pengumpul sampah setelah penghentian iterasi. Itu akan tetap ada ..., tetapi masih berbeda dari$i
iterasinya nanti.sumber