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