<<-
paling berguna dalam hubungannya dengan penutupan untuk mempertahankan keadaan. Berikut adalah bagian dari makalah saya terbaru:
Penutupan adalah fungsi yang ditulis oleh fungsi lain. Penutupan disebut demikian karena menutup lingkungan fungsi induk, dan dapat mengakses semua variabel dan parameter dalam fungsi itu. Ini berguna karena memungkinkan kita untuk memiliki dua level parameter. Satu tingkat parameter (induk) mengontrol cara kerja fungsi. Tingkat lain (anak) melakukan pekerjaan. Contoh berikut menunjukkan bagaimana bisa menggunakan ide ini untuk menghasilkan keluarga fungsi kekuasaan. Fungsi induk ( power
) membuat fungsi anak ( square
dan cube
) yang benar-benar melakukan kerja keras.
power <- function(exponent) {
function(x) x ^ exponent
}
square <- power(2)
square(2) # -> [1] 4
square(4) # -> [1] 16
cube <- power(3)
cube(2) # -> [1] 8
cube(4) # -> [1] 64
Kemampuan untuk mengelola variabel pada dua level juga memungkinkan untuk mempertahankan status di seluruh pemanggilan fungsi dengan memungkinkan fungsi untuk memodifikasi variabel di lingkungan induknya. Kunci untuk mengelola variabel di berbagai tingkat adalah operator penugasan panah ganda <<-
. Tidak seperti penugasan panah tunggal biasa ( <-
) yang selalu berfungsi pada level saat ini, operator panah ganda dapat memodifikasi variabel di level induk.
Ini memungkinkan untuk mempertahankan penghitung yang mencatat berapa kali suatu fungsi telah dipanggil, seperti yang ditunjukkan contoh berikut. Setiap kali new_counter
dijalankan, ia menciptakan lingkungan, menginisialisasi penghitung i
di lingkungan ini, dan kemudian menciptakan fungsi baru.
new_counter <- function() {
i <- 0
function() {
# do something useful, then ...
i <<- i + 1
i
}
}
Fungsi baru adalah penutup, dan lingkungannya adalah lingkungan tertutup. Ketika penutupan counter_one
dan counter_two
dijalankan, masing-masing memodifikasi penghitung di lingkungan terlampir dan kemudian mengembalikan hitungan saat ini.
counter_one <- new_counter()
counter_two <- new_counter()
counter_one() # -> [1] 1
counter_one() # -> [1] 2
counter_two() # -> [1] 1
Akan membantu jika
<<-
dianggap setara denganassign
(jika Anda mengaturinherits
parameter pada fungsi tersebutTRUE
). Keuntungannyaassign
adalah memungkinkan Anda untuk menentukan lebih banyak parameter (misalnya lingkungan), jadi saya lebih suka menggunakanassign
lebih<<-
banyak kasus.Menggunakan
<<-
danassign(x, value, inherits=TRUE)
berarti bahwa "melampirkan lingkungan dari lingkungan yang disediakan dicari sampai variabel 'x' ditemukan." Dengan kata lain, ia akan terus melalui lingkungan dalam urutan sampai menemukan variabel dengan nama itu, dan akan menugaskannya untuk itu. Ini bisa berada dalam lingkup fungsi, atau di lingkungan global.Untuk memahami apa yang dilakukan fungsi-fungsi ini, Anda juga harus memahami lingkungan R (misalnya menggunakan
search
).Saya secara teratur menggunakan fungsi-fungsi ini ketika saya menjalankan simulasi besar dan saya ingin menyimpan hasil antara. Ini memungkinkan Anda untuk membuat objek di luar lingkup fungsi atau
apply
loop yang diberikan . Itu sangat membantu, terutama jika Anda memiliki kekhawatiran tentang loop besar yang berakhir secara tidak terduga (misalnya pemutusan basis data), dalam hal ini Anda bisa kehilangan segalanya dalam proses tersebut. Ini akan sama dengan menulis hasil Anda ke database atau file selama proses yang berjalan lama, kecuali bahwa itu menyimpan hasil dalam lingkungan R sebagai gantinya.Peringatan utama saya dengan ini: hati-hati karena Anda sekarang bekerja dengan variabel global, terutama saat menggunakan
<<-
. Itu berarti bahwa Anda bisa berakhir dengan situasi di mana suatu fungsi menggunakan nilai objek dari lingkungan, ketika Anda mengharapkannya menggunakan yang diberikan sebagai parameter. Ini adalah salah satu hal utama yang coba dihindari oleh pemrograman fungsional (lihat efek samping ). Saya menghindari masalah ini dengan menetapkan nilai saya ke nama variabel unik (menggunakan tempel dengan set atau parameter unik) yang tidak pernah digunakan dalam fungsi, tetapi hanya digunakan untuk caching dan jika saya perlu memulihkan nanti (atau melakukan beberapa meta -Analisis pada hasil antara).sumber
Satu tempat di mana saya menggunakan
<<-
GUI sederhana menggunakan tcl / tk. Beberapa contoh awal memilikinya - karena Anda perlu membuat perbedaan antara variabel lokal dan global untuk statefullness. Lihat misalnyayang menggunakan
<<-
. Kalau tidak, saya setuju dengan Marek :) - pencarian Google dapat membantu.sumber
tkdensity
di R 3.6.0.sumber
<<-
. A for loop akan lebih jelas dalam hal ini.Mengenai hal ini saya ingin menunjukkan bahwa
<<-
operator akan berperilaku aneh ketika diterapkan (salah) dalam for loop (mungkin ada kasus lain juga). Diberikan kode berikut:Anda mungkin berharap bahwa fungsi akan mengembalikan jumlah yang diharapkan, 6, tetapi sebaliknya mengembalikan 0, dengan variabel global
mySum
yang dibuat dan diberi nilai 3. Saya tidak bisa sepenuhnya menjelaskan apa yang sedang terjadi di sini, tetapi tentu saja tubuh for loop bukan 'level' lingkup baru. Sebaliknya, tampaknya R terlihat di luarfortest
fungsi, tidak dapat menemukanmySum
variabel untuk ditetapkan, jadi buat satu dan tetapkan nilai 1, pertama kali melalui loop. Pada iterasi berikutnya, RHS dalam penugasan harus mengacu padamySum
variabel dalam (tidak berubah) sedangkan LHS mengacu pada variabel global. Oleh karena itu setiap iterasi menimpa nilai variabel global ke nilai iterasii
, sehingga memiliki nilai 3 saat keluar dari fungsi.Semoga ini bisa membantu seseorang - ini membuat saya bingung selama beberapa jam hari ini! (BTW, ganti saja
<<-
dengan<-
dan fungsinya berfungsi seperti yang diharapkan).sumber
mySum
tidak pernah bertambah tetapi hanya globalmySum
. Oleh karena itu pada setiap iterasi for for, globalmySum
mendapatkan nilainya0 + i
. Anda dapat mengikuti ini dengandebug(fortest)
.<-
mana saja secara konsisten dalam fungsi jika Anda hanya ingin memperbarui variabel lokal di dalam fungsi.The
<<-
Operator juga dapat berguna untuk Kelas Referensi ketika menulis Metode Referensi . Sebagai contoh:sumber