Saya tertarik pada apa cara "benar" untuk menulis fungsi dengan argumen opsional di R. Seiring waktu, saya menemukan beberapa potong kode yang mengambil rute berbeda di sini, dan saya tidak dapat menemukan posisi yang tepat (resmi). pada topik ini.
Sampai sekarang, saya telah menulis argumen opsional seperti ini:
fooBar <- function(x,y=NULL){
if(!is.null(y)) x <- x+y
return(x)
}
fooBar(3) # 3
fooBar(3,1.5) # 4.5
Fungsi hanya mengembalikan argumennya jika hanya x
disediakan. Itu menggunakan NULL
nilai default untuk argumen kedua dan jika argumen itu kebetulan tidak NULL
, maka fungsi menambahkan dua angka.
Atau, seseorang dapat menulis fungsi seperti ini (di mana argumen kedua perlu ditentukan dengan nama, tetapi orang juga dapat unlist(z)
atau mendefinisikan z <- sum(...)
):
fooBar <- function(x,...){
z <- list(...)
if(!is.null(z$y)) x <- x+z$y
return(x)
}
fooBar(3) # 3
fooBar(3,y=1.5) # 4.5
Secara pribadi saya lebih suka versi pertama. Namun, saya bisa melihat baik dan buruk dengan keduanya. Versi pertama agak kurang rentan terhadap kesalahan, tetapi yang kedua dapat digunakan untuk memasukkan jumlah opsional yang sewenang-wenang.
Apakah ada cara "benar" untuk menentukan argumen opsional di R? Sejauh ini, saya sudah sepakat dengan pendekatan pertama, tetapi keduanya kadang-kadang bisa terasa sedikit "hacky".
xy.coords
melihat pendekatan yang umum digunakan.xy.coords
disebutkan oleh Carl Witthoft l dapat ditemukan di xy.coordsJawaban:
Anda juga dapat menggunakan
missing()
untuk menguji apakah argumeny
diberikan atau tidak :sumber
missing()
juga lebih ekspresif dalam arti bahwa "mengatakan apa artinya". Plus itu memungkinkan pengguna untuk memberikan nilai NULL, di tempat-tempat yang masuk akal!@param x numeric; something something; @param y numeric; **optional** something something; @param z logical; **optional** something something
missing()
mengerikan ketika Anda ingin menyampaikan argumen dari satu fungsi ke fungsi lainnya.Sejujurnya saya suka cara pertama OP benar-benar mulai dengan
NULL
nilai dan kemudian memeriksanyais.null
(terutama karena sangat sederhana dan mudah dimengerti). Ini mungkin tergantung pada cara orang digunakan untuk pengkodean tetapi Hadley tampaknya juga mendukungis.null
cara itu:Dari buku Hadley "Advanced-R" Bab 6, Functions, hal.84 (untuk versi online periksa di sini ):
sumber
NULL
cara ini cukup lama dan mungkin itu sebabnya saya lebih terbiasa ketika saya melihat kode sumber. Sepertinya lebih alami bagi saya. Yang mengatakan, seperti yang Anda katakan basis R mengambil kedua pendekatan itu, itu benar-benar turun ke preferensi individu.is.null
danmissing
tergantung pada konteks dan apa argumen yang digunakan.Ini adalah aturan praktis saya:
Jika nilai default dapat dihitung dari parameter lain, gunakan ekspresi default seperti pada:
jika sebaliknya gunakan yang hilang
Dalam kasus yang jarang Anda anggap pengguna mungkin ingin menentukan nilai default yang berlangsung seluruh sesi R, gunakan
getOption
Jika beberapa parameter berlaku tergantung pada kelas argumen pertama, gunakan S3 generik:
Gunakan
...
hanya ketika Anda meneruskan parameter tambahan ke fungsi lainTerakhir, jika Anda memilih penggunaan
...
tanpa mengalihkan titik ke fungsi lain, ingatkan pengguna bahwa fungsi Anda mengabaikan parameter yang tidak digunakan karena bisa sangat membingungkan jika tidak:sumber
NULL
dalam tanda tangan fungsi, karena lebih nyaman untuk membuat fungsi yang berantai dengan baik.Ada beberapa opsi dan tidak ada yang merupakan cara resmi yang benar dan tidak ada yang benar-benar salah, meskipun mereka dapat menyampaikan informasi yang berbeda ke komputer dan kepada orang lain yang membaca kode Anda.
Untuk contoh yang diberikan, saya pikir pilihan yang paling jelas adalah memberikan nilai default identitas, dalam hal ini lakukan sesuatu seperti:
Ini adalah pilihan terpendek yang ditampilkan sejauh ini dan singkatnya dapat membantu keterbacaan (dan kadang-kadang bahkan kecepatan dalam eksekusi). Jelas bahwa apa yang dikembalikan adalah jumlah x dan y dan Anda dapat melihat bahwa y tidak diberi nilai yang akan menjadi 0 yang bila ditambahkan ke x hanya akan menghasilkan x. Jelas jika sesuatu yang lebih rumit daripada penambahan digunakan maka nilai identitas yang berbeda akan diperlukan (jika ada).
Satu hal yang saya sangat suka tentang pendekatan ini adalah jelas apa nilai default ketika menggunakan
args
fungsi, atau bahkan melihat file bantuan (Anda tidak perlu gulir ke bawah ke rinciannya, itu ada di sana dalam penggunaan ).Kelemahan dari metode ini adalah ketika nilai standarnya kompleks (membutuhkan beberapa baris kode), maka mungkin akan mengurangi keterbacaan untuk mencoba memasukkan semua itu ke dalam nilai default dan
missing
atauNULL
pendekatannya menjadi jauh lebih masuk akal.Beberapa perbedaan lain antara metode akan muncul ketika parameter diturunkan ke fungsi lain, atau saat menggunakan fungsi
match.call
atausys.call
.Jadi saya kira metode "benar" tergantung pada apa yang Anda rencanakan dengan argumen khusus itu dan informasi apa yang ingin Anda sampaikan kepada pembaca kode Anda.
sumber
Saya cenderung lebih suka menggunakan NULL untuk kejelasan tentang apa yang diperlukan dan apa yang opsional. Satu kata peringatan tentang penggunaan nilai default yang bergantung pada argumen lain, seperti yang disarankan oleh Jthorpe. Nilai tidak diatur ketika fungsi dipanggil, tetapi ketika argumen pertama kali direferensikan! Misalnya:
Di sisi lain, jika Anda merujuk y sebelum mengubah x:
Ini agak berbahaya, karena membuatnya sulit untuk melacak apa yang "y" diinisialisasi seolah-olah itu tidak dipanggil sejak awal dalam fungsi.
sumber
Hanya ingin menunjukkan bahwa
sink
fungsi bawaan memiliki contoh bagus berbagai cara untuk mengatur argumen dalam suatu fungsi:sumber
bagaimana dengan ini?
Lalu coba:
sumber