Penjelasan yang lebih baik tentang kapan harus menggunakan Impor / Tergantung

148

Manual " Writing R Extensions " menyediakan panduan berikut tentang kapan harus menggunakan Impor atau Tergantung:

Aturan umum adalah

  • Paket yang hanya memerlukan namespace untuk memuat paket menggunakan pkgname harus terdaftar di bidang 'Impor' dan bukan di bidang 'Tergantung'.
  • Paket yang perlu dilampirkan untuk berhasil memuat paket menggunakan pkgname harus terdaftar di bidang 'Tergantung' saja.

Bisakah seseorang memberikan kejelasan lebih banyak tentang ini? Bagaimana saya tahu ketika paket saya hanya perlu ruang nama dimuat versus ketika saya perlu paket untuk dilampirkan? Apa contoh keduanya? Saya pikir paket tipikal hanyalah kumpulan fungsi yang terkadang memanggil fungsi dalam paket lain (di mana beberapa pekerjaan sudah dikodekan). Apakah skenario 1 atau 2 di atas?

Edit

Saya menulis posting blog dengan bagian tentang topik khusus ini (mencari 'Impor v Tergantung'). Visual membuatnya jauh lebih mudah untuk dipahami.

SFun28
sumber
1
Posting blog Anda memberi tahu saya segalanya tentang struktur paket, ketika saya mulai merencanakan modul . Terima kasih!
Konrad Rudolph

Jawaban:

143

"Imports"lebih aman daripada "Depends"(dan juga membuat paket menggunakannya 'warga negara yang lebih baik' sehubungan dengan paket lain yang menggunakannya "Depends").

Sebuah "Depends"upaya direktif untuk memastikan bahwa fungsi dari paket lain yang tersedia dengan melampirkan paket lain untuk path pencarian utama (yaitu daftar lingkungan dikembalikan oleh search()). Strategi ini, bagaimanapun, dapat digagalkan jika paket lain, yang dimuat kemudian, menempatkan fungsi yang identik sebelumnya di jalur pencarian. Ruang ( dalam SoDA ) menggunakan contoh fungsi "gam", yang ditemukan di kedua paket gamdan mgcv. Jika dua paket lain dimuat, satu tergantung gamdan satu tergantung mgcv, fungsi yang ditemukan oleh panggilan gam()akan tergantung pada urutan dua paket tersebut dilampirkan. Tidak baik.

Sebuah "Imports"direktif harus digunakan untuk setiap paket pendukung yang fungsinya adalah untuk ditempatkan di <imports:packageName>(dicari segera setelah <namespace:packageName>), bukan di jalan pencarian biasa. Jika salah satu paket dalam contoh di atas menggunakan "Imports"mekanisme (yang juga membutuhkan importatau importFromarahan dalam NAMESPACEfile), masalah akan diperbaiki dengan dua cara. (1) Paket itu sendiri akan mendapatkan kendali atas mgcvfungsi yang digunakan. (2) Dengan menjaga jalur pencarian utama bersih dari objek yang diimpor, itu bahkan tidak akan berpotensi memecah ketergantungan paket lain pada mgcvfungsi lainnya .

Inilah sebabnya mengapa menggunakan namespace adalah praktik yang sangat baik, mengapa sekarang diberlakukan oleh CRAN, dan (khususnya) mengapa menggunakan "Imports"lebih aman daripada menggunakan "Depends".


Diedit untuk menambahkan peringatan penting:

Ada satu pengecualian sayangnya umum untuk saran di atas: jika paket Anda bergantung pada paket Ayang sendiri "Depends"pada paket lain B, paket Anda mungkin akan perlu melampirkan Adengan "Dependsdirektif.

Ini karena fungsi-fungsi dalam paket Aditulis dengan harapan bahwa paket Bdan fungsinya akan dilampirkan pada search()path .

Sebuah "Depends"direktif akan memuat dan melampirkan paket A, di mana titik paket A's sendiri "Depends"direktif akan, dalam reaksi berantai, penyebab paket Byang akan dimuat dan melekat juga. Fungsi dalam paket Akemudian akan dapat menemukan fungsi dalam paket Byang mereka andalkan.

Sebuah "Imports"direktif akan memuat tetapi tidak melampirkan paket Adan akan tidak beban atau melampirkan paket B. ( "Imports", setelah semua, mengharapkan bahwa penulis paket menggunakan mekanisme namespace, dan paket itu Aakan menggunakan "Imports"untuk menunjuk ke fungsi apa pun Byang memerlukan akses.) Panggilan oleh fungsi Anda ke fungsi dalam paket Ayang bergantung pada fungsi dalam paket Bakan akibatnya gagal.

Hanya dua solusi untuk:

  1. Apakah paket Anda melampirkan paket Amenggunakan "Depends"arahan.
  2. Lebih baik dalam jangka panjang, hubungi pengelola paket Adan minta mereka untuk melakukan pekerjaan yang lebih hati-hati dalam membangun ruang nama mereka (dalam kata-kata Martin Morgan dalam jawaban terkait ini ).
Josh O'Brien
sumber
1
Baru-baru ini mengajukan pertanyaan serupa dan baru-baru ini bergelut dengan isu-isu ini, ini adalah konsep yang halus dan sering dikomunikasikan. Saya akan merujuk Anda ke sini untuk penjelasan lain: stackoverflow.com/questions/7880355/…
Bryan Hanson
@BryanHanson - Terima kasih telah menulis catatan di tautan itu. Perbedaan antara Importsdan Dependspersyaratan versi wrt dan memeriksa contoh dalam .Rdfile memang halus dan patut diketahui.
Josh O'Brien
1
Peringatan tentang ketergantungan yang menggunakan 'Tergantung' adalah hal yang mengerikan. Itu berarti saya pada dasarnya tidak dapat menggunakan 'Impor' dalam paket saya sampai semua orang juga. = (
Ken Williams
Satu hal yang saya masih belum jelas adalah, jika saya menulis paket, dan saya ingin Imports: ggplot2, mengapa paket saya tidak menemukan autoplotfungsinya? Jelas Dependsmelampirkan pustaka paket ggplot2dan jadi tidak ada masalah. misalnya saya memiliki fungsi autoplot.myFunction() yang menggunakan @import ggplot2tag dan paket saya miliki Imports: ggplot2tetapi saya mendapatkan kesalahan: Error in eval(expr, envir, enclos) : could not find function "autoplot"ketika saya mencoba menggunakannya.
nathaneastwood
1
@ Willem Terima kasih. Anda tentu saja benar, dan saya telah mengedit jawaban untuk menjernihkan konten yang menyesatkan. Bagian dari apa yang membuat ini rumit untuk jawabannya adalah bahwa, sementara OP dibingkai pertanyaannya dengan mengacu pada Dependsdan Importsbagian DESCRIPTION, dia benar-benar bertanya tentang apa yang "mengimpor" fungsi (bukan "tergantung" pada itu) berarti. Karena yang terakhir itu adalah pertanyaan yang saya coba jawab (dan - saya curiga - apa yang ingin diketahui oleh kebanyakan orang yang mencari jawaban ini), saya akan meninggalkan jawaban yang sebaliknya tidak berubah.
Josh O'Brien
31

Hadley Wickham memberikan penjelasan yang mudah ( http://r-pkgs.had.co.nz/namespace.html ):

Mendaftarkan suatu paket di salah satu Dependsatau Importsmemastikan bahwa itu diinstal ketika diperlukan. Perbedaan utama adalah di mana Importshanya memuat paket, Dependsmenempelkannya. Tidak ada perbedaan lain. [...]

Kecuali jika ada alasan bagus sebaliknya, Anda harus selalu mendaftar paket Importstidak Depends. Itu karena paket yang baik mandiri, dan meminimalkan perubahan pada lingkungan global (termasuk jalur pencarian). Satu-satunya pengecualian adalah jika paket Anda dirancang untuk digunakan bersama dengan paket lain. Misalnya, paket analog dibuat di atas vegan. Ini tidak berguna tanpa vegan, sehingga memiliki vegan di Dependsbukannya Imports. Demikian pula, ggplot2 harus benar-benar Bergantung pada skala, bukan Mengimpornya.

majom
sumber
15

Kamar di SfDA mengatakan untuk menggunakan 'Impor' ketika paket ini menggunakan mekanisme 'namespace' dan karena semua paket sekarang diharuskan memilikinya, maka jawabannya sekarang mungkin selalu menggunakan 'Impor'. Dalam paket-paket sebelumnya bisa dimuat tanpa benar-benar memiliki ruang nama dan dalam hal ini Anda harus menggunakan Depends.

IRTFM
sumber
2
ketika paket ditentukan dalam "impor" dan saya ingin menggunakan fungsi dalam paket, apakah fungsi saya perlu memanggil pustaka (...) atau apakah semua fungsi sudah tersedia di jalur pencarian? Juga, apa itu SfDA? tautan?
SFun28
2
Perangkat Lunak untuk Analisis Data : springer.com/statistics/computanional+statistics/book/ ... ... untuk pertanyaan Anda, saya tidak tahu jawabannya, tetapi Anda bisa meretas paket tes minimal dengan mudah dan menemukan jawabannya secara empiris ...
Ben Bolker
1
SfDA == "Perangkat Lunak untuk Analisis Data". [65] di r-project.org/doc/bib/R-books.html . Jika suatu paket menentukan paket lain, Anda akan melihat pesan yang memberi tahu Anda tentang pemuatan dependen (enkripsi) dan impor (asi) ketika Anda menggunakan salah satu pustaka () atau mengharuskan () di konsol. Ya, mereka seharusnya sudah tersedia.
IRTFM
4
+1 - Ini adalah kesan kuat saya juga. Juga, paket yang ditentukan dalam impor akan dicari segera setelah <namespace:packageName>, sebagai bagian dari <imports:packageName>. Tidak ada panggilan lebih lanjut library()yang diperlukan, dan R tidak akan memberi tahu Anda di konsol pada waktu pemuatan paket kecuali Importpaket ed tidak dapat ditemukan.
Josh O'Brien
5

Berikut adalah pertanyaan sederhana untuk membantu Anda memutuskan mana yang akan digunakan:

Apakah paket Anda mengharuskan pengguna akhir untuk memiliki akses langsung ke fungsi-fungsi paket lain?

  • TIDAK -> Impor (jawaban paling umum)
  • YA -> Tergantung

Satu-satunya waktu Anda harus menggunakan 'Tergantung' adalah ketika paket Anda merupakan add-on atau pendamping untuk paket lain, di mana pengguna akhir Anda akan menggunakan fungsi dari kedua paket Anda dan paket 'Tergantung' dalam kode mereka. Jika pengguna akhir Anda hanya akan berinteraksi dengan fungsi Anda, dan paket lainnya hanya akan melakukan pekerjaan di belakang layar, maka gunakan 'Impor' sebagai gantinya.

Peringatan untuk ini adalah bahwa jika Anda menambahkan paket ke 'Impor', seperti biasanya, kode Anda harus merujuk ke fungsi dari paket itu, menggunakan sintaks namespace lengkap, misalnya dplyr::mutate(), alih-alih adil mutate(). Itu membuat kode sedikit clunkier untuk dibaca, tapi itu harga kecil untuk membayar paket kebersihan yang lebih baik.

Aaron Cooley
sumber