คำอธิบายที่ดีขึ้นเกี่ยวกับเวลาที่จะใช้การนำเข้า / ขึ้นอยู่กับ


148

คู่มือ " การเขียนส่วนขยาย R " ให้คำแนะนำต่อไปนี้เกี่ยวกับเวลาที่จะใช้การนำเข้าหรือขึ้นอยู่กับ:

กฎทั่วไปคือ

  • แพคเกจที่จำเป็นต้องใช้ namespace เท่านั้นในการโหลดแพ็กเกจโดยใช้ไลบรารี่ (pkgname) จะต้องแสดงรายการในฟิลด์ 'Imports' และไม่อยู่ในฟิลด์ 'Depends'
  • แพ็กเกจที่ต้องแนบเพื่อโหลดแพ็กเกจสำเร็จโดยใช้ไลบรารี่ (pkgname) จะต้องแสดงรายการในฟิลด์ 'ขึ้นอยู่กับ' เท่านั้น

บางคนสามารถให้ความกระจ่างเกี่ยวกับเรื่องนี้ได้มากกว่านี้หรือไม่? ฉันจะรู้ได้อย่างไรว่าเมื่อใดที่แพ็คเกจของฉันต้องการโหลดเนมสเปซเมื่อเทียบกับเมื่อฉันต้องการแพ็กเกจเท่านั้น ตัวอย่างของทั้งสองคืออะไร ฉันคิดว่าแพคเกจทั่วไปเป็นเพียงชุดของฟังก์ชั่นที่บางครั้งเรียกฟังก์ชั่นในแพ็คเกจอื่น ๆ (ที่มีการทำงานบางส่วนได้รับการเข้ารหัสแล้ว) สถานการณ์นี้เป็น 1 หรือ 2 ข้างต้นหรือไม่

แก้ไข

ฉันเขียนโพสต์บล็อกพร้อมส่วนในหัวข้อเฉพาะนี้ (ค้นหา 'Imports v Depends') ภาพทำให้เข้าใจได้ง่ายขึ้นมาก


1
โพสต์บล็อกของคุณบอกฉันทุกอย่างที่เกี่ยวกับโครงสร้างแพคเกจกลับมาเมื่อผมเริ่มวางแผนโมดูล ขอบคุณ!
Konrad Rudolph

คำตอบ:


143

"Imports"ปลอดภัยกว่า"Depends"(และทำให้แพ็คเกจที่ใช้เป็น 'พลเมืองที่ดีขึ้น' เมื่อเทียบกับแพ็คเกจอื่น ๆ ที่ใช้งาน"Depends")

"Depends"พยายามสั่งเพื่อให้มั่นใจว่าการทำงานจากแพคเกจอื่นสามารถใช้ได้โดยการติดตั้งแพคเกจอื่น ๆ ไปยังเส้นทางการค้นหาหลัก (เช่นรายการของสภาพแวดล้อมที่ส่งกลับโดยsearch()) อย่างไรก็ตามกลยุทธ์นี้สามารถป้องกันได้หากมีการโหลดแพคเกจอื่นในภายหลังวางฟังก์ชันที่มีชื่อเหมือนกันก่อนหน้านี้บนเส้นทางการค้นหา Chambers ( ใน SoDA ) ใช้ตัวอย่างของฟังก์ชัน"gam"ซึ่งพบได้ทั้งในgamและmgcvแพ็คเกจ หากมีการโหลดแพ็กเกจอื่นสองแพคเกจหนึ่งแพ็กเกจนั้นขึ้นอยู่กับแพ็กเกจที่gamขึ้นอยู่กับmgcvฟังก์ชั่นที่พบโดยการเรียกไปยังgam()จะขึ้นอยู่กับลำดับที่แนบแพ็กเกจทั้งสอง ไม่ดี.

"Imports"สั่งควรจะใช้สำหรับแพคเกจการสนับสนุนใด ๆ ที่มีฟังก์ชั่นจะถูกวางไว้ใน<imports:packageName>(สืบค้นทันทีหลังจาก<namespace:packageName>) แทนในเส้นทางการค้นหาปกติ หากหนึ่งในแพ็กเกจในตัวอย่างด้านบนใช้"Imports"กลไก (ซึ่งจำเป็นต้องมีimportหรือimportFromคำสั่งในNAMESPACEไฟล์) เรื่องต่างๆจะได้รับการปรับปรุงในสองวิธี (1) แพ็คเกจจะได้รับการควบคุมว่าmgcvจะใช้ฟังก์ชันใด (2) โดยการรักษาเส้นทางการค้นหาหลักที่ชัดเจนของวัตถุที่นำเข้ามันจะไม่ได้ทำลายการพึ่งพาแพคเกจอื่น ๆ ในmgcvฟังก์ชั่นอื่น ๆ

นี่คือเหตุผลที่ใช้ namespaces เป็นวิธีที่ดีดังกล่าวว่าทำไมมันจะถูกบังคับใช้ในขณะนี้โดย CRAN และ (โดยเฉพาะอย่างยิ่งใน) ว่าทำไมการใช้จะปลอดภัยกว่าการใช้"Imports""Depends"


แก้ไขเพื่อเพิ่มข้อแม้ที่สำคัญ:

มีข้อยกเว้นอย่างหนึ่งที่พบได้ทั่วไปในคำแนะนำข้างต้น: หากแพ็คเกจของคุณใช้แพ็คเกจAที่"Depends"อยู่ในแพ็คเกจอื่นแพ็คเกจBของคุณอาจจำเป็นต้องแนบมาAพร้อมกับ"Dependsคำสั่ง

เพราะนี่คือฟังก์ชั่นในแพคเกจAที่ถูกเขียนขึ้นด้วยความคาดหวังว่าแพคเกจBและหน้าที่ของตนจะได้รับการติดอยู่กับsearch()เส้นทาง

"Depends"สั่งจะโหลดและแนบแพคเกจAที่จุดแพคเกจAของตัวเอง"Depends"สั่งจะในปฏิกิริยาลูกโซ่, แพคเกจสาเหตุBที่จะโหลดและติดอยู่เช่นกัน ฟังก์ชั่นในแพ็คเกจAจะสามารถค้นหาฟังก์ชั่นในแพ็คเกจBที่พวกเขาพึ่งพาได้

"Imports"สั่งจะโหลด แต่ไม่ได้แนบแพคเกจAและจะไม่โหลดมิได้Bแนบแพคเกจ ( "Imports"หลังจากทั้งหมดคาดว่านักเขียนแพคเกจที่มีการใช้กลไก namespace และแพคเกจที่Aจะใช้"Imports"ในการชี้ไปที่ฟังก์ชั่นใด ๆ ในBการที่จะต้องเข้าถึง.) โทรโดยฟังก์ชั่นของคุณเพื่อฟังก์ชั่นใด ๆ ในแพคเกจAที่พึ่งพาฟังก์ชั่นในแพคเกจBประสงค์ จึงล้มเหลว

โซลูชันที่สองเท่านั้นคือ:

  1. ให้แพ็คเกจของคุณแนบแพ็คเกจAโดยใช้"Depends"คำสั่ง
  2. ดีกว่าในระยะยาวติดต่อผู้ดูแลบรรจุภัณฑ์Aและขอให้พวกเขาทำงานอย่างระมัดระวังมากขึ้นในการสร้างเนมสเปซของพวกเขา (ในคำพูดของ Martin Morgan ในคำตอบที่เกี่ยวข้องนี้ )

1
เมื่อเร็ว ๆ นี้ถามคำถามที่คล้ายกันและเมื่อเร็ว ๆ นี้ต่อสู้กับปัญหาเหล่านี้อย่างมีนัยสำคัญเหล่านี้เป็นแนวคิดที่บอบบางและมักจะสื่อสารไม่ดี ฉันจะแนะนำคุณที่นี่เพื่อดูคำอธิบายเพิ่มเติม: stackoverflow.com/questions/7880355/…
Bryan Hanson

@BryanHanson - ขอบคุณที่เขียนบันทึกที่ลิงค์นั้น ความแตกต่างระหว่างImportsและDependsข้อกำหนดของเวอร์ชัน wrt และการตรวจสอบตัวอย่างใน.Rdไฟล์เป็นสิ่งที่ลึกซึ้งและคุ้มค่าที่ได้รู้
Josh O'Brien

1
ข้อแม้เกี่ยวกับการพึ่งพาที่ใช้ 'ขึ้นอยู่กับ' เป็นสิ่งที่น่ากลัว หมายความว่าฉันไม่สามารถใช้ 'Imports' ในแพ็คเกจของฉันได้จนกว่าคนอื่นจะใช้เช่นกัน = (
Ken Williams

สิ่งหนึ่งที่ฉันยังไม่ชัดเจนคือถ้าฉันเขียนแพคเกจและฉันต้องการImports: ggplot2ทำไมแพคเกจของฉันแล้วไม่พบautoplotฟังก์ชั่น? เห็นได้ชัดว่าDependsแนบไลบรารีแพคเกจของggplot2และดังนั้นจึงไม่มีปัญหา เช่นฉันมีฟังก์ชั่นautoplot.myFunction() ที่ใช้@import ggplot2แท็กและแพ็คเกจของฉันมีImports: ggplot2แต่ฉันได้รับข้อผิดพลาด: Error in eval(expr, envir, enclos) : could not find function "autoplot"เมื่อฉันพยายามที่จะใช้
nathaneastwood

1
@ วิลเล็มขอบคุณ คุณถูกต้องแน่นอนและฉันได้แก้ไขคำตอบเพื่อล้างเนื้อหาที่ทำให้เข้าใจผิด ส่วนหนึ่งของสิ่งที่ทำให้คำตอบที่ซับซ้อนนี้คือในขณะที่ OP กำหนดกรอบคำถามของเขาโดยอ้างอิงถึงDependsและImportsส่วนต่าง ๆDESCRIPTIONเขาถามว่า "การนำเข้า" ฟังก์ชั่น (หมายถึง "ขึ้นอยู่กับ") หมายความว่าอย่างไร เนื่องจากหลังนั้นเป็นคำถามที่ฉันพยายามตอบ (และ - ฉันสงสัย - สิ่งที่ผู้คนส่วนใหญ่ค้นหาคำตอบนี้อยากรู้) ฉันจะทิ้งคำตอบไว้ไม่เปลี่ยนแปลง
Josh O'Brien

31

Hadley Wickham ให้คำอธิบายง่ายๆ ( http://r-pkgs.had.co.nz/namespace.html ):

การแสดงรายการแพคเกจอย่างใดอย่างหนึ่งDependsหรือImportsตรวจสอบให้แน่ใจว่ามีการติดตั้งเมื่อจำเป็น ความแตกต่างที่สำคัญคือที่ที่ImportsเพียงโหลดแพคเกจDependsแนบมัน ไม่มีความแตกต่างอื่น ๆ [ ... ]

เว้นแต่จะมีเหตุผลที่ดีมิฉะนั้นคุณควรแพคเกจในรายการไม่ได้Imports Dependsนั่นเป็นเพราะแพคเกจที่ดีนั้นมีอยู่ในตัวเองและลดการเปลี่ยนแปลงสภาพแวดล้อมโลกให้น้อยที่สุด (รวมถึงเส้นทางการค้นหา) ข้อยกเว้นเพียงอย่างเดียวคือถ้าแพ็คเกจของคุณถูกออกแบบมาเพื่อใช้ร่วมกับแพ็คเกจอื่น ตัวอย่างเช่นแพ็คเกจอะนาล็อกจะถูกสร้างขึ้นที่ด้านบนของวีแก้น มันไม่ได้มีประโยชน์โดยไม่ต้องมังสวิรัติจึงมีอาหารมังสวิรัติในแทนDepends Importsในทำนองเดียวกัน ggplot2 ควรขึ้นอยู่กับเครื่องชั่งมากกว่าการนำเข้า


15

Chambers ใน SfDA บอกว่าจะใช้ 'Imports' เมื่อแพ็คเกจนี้ใช้กลไก 'namespace' และเนื่องจากแพ็คเกจทั้งหมดจำเป็นต้องมีในตอนนี้ดังนั้นคำตอบจึงอาจใช้ 'Imports' เสมอ ในแพคเกจที่ผ่านมาสามารถโหลดได้โดยไม่ต้องมี namespaces จริงและในกรณีที่คุณจะต้องใช้ขึ้นอยู่กับ


2
เมื่อระบุแพ็คเกจใน "นำเข้า" และฉันต้องการใช้ฟังก์ชั่นในแพ็คเกจฟังก์ชั่นของฉันเองจำเป็นต้องเรียกไลบรารี่ (... ) หรือฟังก์ชั่นทั้งหมดที่มีอยู่ในพา ธ การค้นหาหรือไม่? นอกจากนี้ SfDA คืออะไร การเชื่อมโยง?
SFun28

2
ซอฟต์แวร์สำหรับการวิเคราะห์ข้อมูล : springer.com/statistics/computanional+statistics/book/ ...... สำหรับคำถามของคุณฉันไม่รู้คำตอบในทันที แต่คุณสามารถแฮ็กแพ็คเกจทดสอบขั้นต่ำได้ง่ายๆและหาคำตอบได้ง่าย สังเกตุ ...
Ben Bolker

1
SfDA == "ซอฟต์แวร์สำหรับการวิเคราะห์ข้อมูล" [65] ที่r-project.org/doc/bib/R-books.html หากแพ็คเกจระบุแพ็คเกจอื่นคุณควรเห็นข้อความแจ้งให้คุณทราบเกี่ยวกับการโหลดการพึ่งพา (encies) และการนำเข้า (ations) เมื่อคุณใช้ไลบรารี () หรือ require () ที่คอนโซล ใช่พวกเขาควรจะพร้อมใช้งาน
IRTFM

4
+1 - นี่คือความประทับใจที่แข็งแกร่งของฉันเช่นกัน นอกจากนี้แพคเกจที่ระบุไว้ในการนำเข้าจะค้นหาทันทีหลังจากที่เป็นส่วนหนึ่งของ<namespace:packageName> <imports:packageName>ไม่ต้องการการโทรเพิ่มเติมlibrary()และ R จะไม่แจ้งให้คุณทราบที่คอนโซล ณ เวลาที่โหลดแพ็กเกจเว้นแต่Importจะไม่พบแพ็คเกจ ed
Josh O'Brien

5

นี่เป็นคำถามง่าย ๆ ที่จะช่วยคุณตัดสินใจว่าจะใช้อะไร:

แพ็คเกจของคุณต้องการให้ผู้ใช้ปลายทางเข้าถึงฟังก์ชั่นของแพ็คเกจอื่นได้โดยตรงหรือไม่?

  • NO -> การนำเข้า (คำตอบที่พบบ่อยที่สุด)
  • ใช่ -> ขึ้นอยู่กับ

ครั้งเดียวที่คุณควรใช้ 'ขึ้นอยู่กับ' คือเมื่อแพ็คเกจของคุณเป็นส่วนเสริมหรือเป็นคู่หูในแพ็คเกจอื่นซึ่งผู้ใช้ของคุณจะใช้ฟังก์ชันจากทั้งแพ็คเกจของคุณและแพคเกจ 'ขึ้นอยู่กับ' ในรหัสของพวกเขา หากผู้ใช้ปลายทางของคุณจะเชื่อมต่อกับฟังก์ชั่นของคุณเท่านั้นและแพ็คเกจอื่น ๆ จะทำงานได้เพียงเบื้องหลังเท่านั้นให้ใช้ 'Imports' แทน

ข้อแม้นี้ก็คือว่าถ้าคุณเพิ่มแพคเกจจะ 'นำเข้า' ในขณะที่คุณมักจะควรโค้ดของคุณจะต้องดูการทำงานจากแพคเกจที่ใช้ไวยากรณ์ namespace เต็มรูปแบบเช่นแทนเพียงdplyr::mutate() mutate()มันทำให้รหัสเล็ก ๆ น้อย ๆ ที่จะอ่าน แต่มันเป็นราคาขนาดเล็กที่จะจ่ายสำหรับสุขอนามัยแพคเกจที่ดีขึ้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.