Bahasa R memiliki fitur bagus untuk mendefinisikan fungsi yang dapat mengambil sejumlah variabel argumen. Misalnya, fungsi data.frame
mengambil sejumlah argumen, dan setiap argumen menjadi data untuk kolom dalam tabel data yang dihasilkan. Contoh penggunaan:
> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi"))
letters numbers notes
1 a 1 do
2 b 2 re
3 c 3 mi
Tanda tangan fungsi mencakup elipsis, seperti ini:
function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,
stringsAsFactors = default.stringsAsFactors())
{
[FUNCTION DEFINITION HERE]
}
Saya ingin menulis fungsi yang melakukan sesuatu yang serupa, mengambil beberapa nilai dan mengkonsolidasikannya ke dalam nilai pengembalian tunggal (serta melakukan beberapa pemrosesan lainnya). Untuk melakukan ini, saya perlu mencari cara untuk "membongkar" ...
dari argumen fungsi di dalam fungsi. Saya tidak tahu bagaimana melakukan ini. Baris yang relevan dalam definisi fungsi data.frame
adalah object <- as.list(substitute(list(...)))[-1L]
, yang saya tidak bisa memahaminya.
Jadi bagaimana saya bisa mengubah elipsis dari tanda tangan fungsi menjadi, misalnya, daftar?
Untuk lebih spesifik, bagaimana saya bisa menulis get_list_from_ellipsis
dalam kode di bawah ini?
my_ellipsis_function(...) {
input_list <- get_list_from_ellipsis(...)
output_list <- lapply(X=input_list, FUN=do_something_interesting)
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
Edit
Tampaknya ada dua cara yang memungkinkan untuk melakukan ini. Mereka as.list(substitute(list(...)))[-1L]
dan list(...)
. Namun, keduanya tidak melakukan hal yang persis sama. (Untuk perbedaan, lihat contoh dalam jawaban.) Adakah yang bisa memberi tahu saya apa perbedaan praktis di antara mereka, dan mana yang harus saya gunakan?
list
danc
fungsinya bekerja dengan cara ini, tetapi keduanya primitif, jadi saya tidak dapat dengan mudah memeriksa kode sumber mereka untuk memahami cara kerjanya.rbind.data.frame
gunakan cara ini.list(...)
memadai, mengapa R builtin sepertidata.frame
menggunakan formulir yang lebih panjangas.list(substitute(list(...)))[-1L]
?data.frame
, saya tidak tahu jawabannya (yang mengatakan, saya yakin bahwa ada adalah alasan yang baik untuk itu). Saya menggunakanlist()
untuk tujuan ini dalam paket saya sendiri dan belum menemukan masalah dengannya.Hanya untuk menambahkan tanggapan Shane dan Dirk: menarik untuk dibandingkan
dengan
Sebagaimana adanya, versi mana pun tampaknya cocok untuk keperluan Anda
my_ellipsis_function
, meskipun yang pertama jelas lebih sederhana.sumber
Anda sudah memberikan setengah jawaban. Mempertimbangkan
Jadi ini mengambil dua argumen
a
danb
dari panggilan dan mengubahnya menjadi daftar. Bukankah itu yang Anda minta?sumber
[[1]]
. Juga, saya ingin tahu bagaimana mantra sihiras.list(substitute(list(...)))
bekerja.list(...)
menciptakanlist
objek berdasarkan argumen. Kemudiansubstitute()
buat pohon parse untuk ekspresi yang tidak dievaluasi; lihat bantuan untuk fungsi ini. Serta teks lanjutan yang bagus pada R (atau S). Ini bukan hal sepele.[[-1L]]
bagian (dari pertanyaan saya)? Bukankah seharusnya begitu[[1]]
?print(c(1:3)[-1])
akan mencetak 2 dan 3 saja. IniL
adalah cara baru untuk memastikan akhirnya menjadi bilangan bulat, ini banyak dilakukan di sumber R.[[1]]
dan$a
indeks membuat saya berpikir bahwa daftar bersarang terlibat. Tetapi sekarang saya melihat bahwa apa yang sebenarnya Anda dapatkan adalah daftar yang saya inginkan, tetapi dengan elemen tambahan di bagian depan. Maka[-1L]
masuk akal. Di mana elemen tambahan pertama itu berasal? Dan adakah alasan saya harus menggunakan ini bukan hanyalist(...)
?Ini berfungsi seperti yang diharapkan. Berikut ini adalah sesi interaktif:
Sama, kecuali dengan argumen default:
Seperti yang Anda lihat, Anda bisa menggunakan ini untuk memberikan argumen 'ekstra' ke fungsi di dalam fungsi Anda jika defaultnya tidak seperti yang Anda inginkan dalam kasus tertentu.
sumber