ความแตกต่างระหว่างการใช้งานและความต้องการ


155

ใครสามารถอธิบายความแตกต่างระหว่างuseและrequireทั้งสองเมื่อใช้โดยตรงและเป็น:useและ:requireในnsมาโคร


2
ดูstackoverflow.com/questions/10358149/…สำหรับแมโคร ns ใน Clojure 1.4 ก็แนะนำให้คุณใช้: ต้องการโดยการตั้งค่า: ใช้
Korny

คำตอบ:


101

requireโหลด libs (ที่ไม่ได้โหลดแล้ว) useไม่เหมือนกันบวกมันหมายถึง namespaces ของพวกเขาด้วยclojure.core/refer(เพื่อให้คุณยังได้รับความเป็นไปได้ของการใช้:excludeฯลฯ เช่นเดียวกับclojure.core/refer) แนะนำให้ใช้ทั้งสองอย่างnsแทนที่จะใช้โดยตรง


3
ถ้าฉันต้องการ lib foo แล้วใช้ bar ใน foo ฉันต้องเขียน foo / bar ทุกครั้งใช่ไหม ทำไมคุณต้องการโหลด lib ใน ns แต่ไม่อ้างอิงมันใน ns? ฉันเดาว่าคุณอาจกังวลเกี่ยวกับการชนกันและคุณไม่ต้องการที่จะกระทบยอดพวกเขาใช่มั้ย
Jegschemesch

12
ไม่ต้องกระทบยอดเป็นจุดที่ดีและโดยทั่วไปมีรูปแบบการเขียนโปรแกรมที่บอกว่า "เนมสเปซเป็นความคิดที่ยอดเยี่ยมมากเราควรมีพวกมันมากขึ้น" (จาก "The Zen of Python") - เช่นลักษณะที่แนะนำ ไม่ได้ใช้ "using namespace foo;" ใน C ++ เพื่อให้ผู้อ่านและผู้ดูแลรหัสไม่ต้องกังวล "แถบนี้มาจากไหน" แต่ดู foo :: bar ที่ชัดเจนยิ่งขึ้นแทน ต้องการ (vs use) รองรับสไตล์ "namespaces ที่ชัดเจน" นี้
Alex Martelli

2
อเล็กซ์ให้คำตอบที่ดี แต่ล้าสมัย @overthink ชี้ให้เห็นด้านล่างหลังจากคำตอบนี้ได้รับการแนะนำให้ใช้มากกว่าการใช้ ดู: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper

แม้ว่านี่จะเป็นคำตอบที่ได้รับการยอมรับและได้รับการโหวตมากที่สุด แต่ก็เก่าและเป็นตัวแทนของมุมมองที่ล้าสมัย คำตอบที่ดีกว่าคือจาก @rzv: stackoverflow.com/a/16429572/172272
Didier A.

65

มันเป็นสำนวนที่จะรวมถึงฟังก์ชั่นภายนอกและrequire referคุณหลีกเลี่ยงความขัดแย้งของเนมสเปซคุณรวมเฉพาะฟังก์ชั่นที่คุณใช้จริง ๆ / ต้องการและคุณประกาศตำแหน่งของแต่ละฟังก์ชั่นอย่างชัดเจน:

(ns project.core
    (:require [ring.middleware.reload :refer [wrap-reload]]))

ฉันไม่ต้องเรียกใช้ฟังก์ชันนี้โดยนำหน้าด้วยเนมสเปซของมัน:

(wrap-reload) ; works

หากคุณไม่ได้ใช้referคุณจะต้องนำหน้าด้วยเนมสเปซ:

(ring.middleware.reload/wrap-reload) ; works if you don't use refer in your require

หากคุณเลือกuseใช้แทน (สวยมาก) เสมอonly:

(ns project.core
    (:use [ring.middleware.reload :only [wrap-reload]]))

มิฉะนั้นคุณจะรวมทุกอย่างเข้าด้วยกันทำให้เป็นทั้งการดำเนินการที่มีขนาดใหญ่เกินความจำเป็นและสับสนมากสำหรับโปรแกรมเมอร์คนอื่น ๆ

นอกจากนี้ฉันขอแนะนำบล็อกนี้เป็นแหล่งข้อมูลสำหรับการเรียนรู้เพิ่มเติมเกี่ยวกับเนมสเปซ Clojure


คุณรู้หรือไม่ว่ามีความแตกต่างในตอนท้ายระหว่าง(:use foo :only [bar])และ(:require foo :refer [bar])? ดูเหมือนว่าแปลกที่มีสองวิธีในการทำเช่นนี้
คิดมาก

10
ดูเหมือนว่าstackoverflow.com/a/10370672/69689ตอบคำถามของฉัน กล่าวโดยย่อ: (:require .. :refer ..)เป็นวิธีใหม่ในการทำสิ่งเดียวกันที่อนุญาตให้คุณเลิกใช้งานได้อย่างมีประสิทธิภาพ:useซึ่งมีข้อเสียอยู่บ้าง
คิดมาก

เป็นตัวอย่างที่ดี ฉันรักตัวอย่างสิ่งนี้สมเหตุสมผลมาก
Astrid

35

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

เช่น:

 (ใช้ '[clojure-contrib.duck-streams: เท่านั้น (ผู้อ่านนักเขียน)])
หรือดียิ่งขึ้นระบุที่ด้านบนของไฟล์ในนิยาม namespace:

(ns com.me.project
   (: ใช้ [clojure.contrib.test-is: only (deftest คือ run-tests)])

3
ขอบคุณสำหรับการรวม (pun) (ns ...)ไวยากรณ์ ฉันได้รับการมองหา (use ...)แต่ตัวอย่างที่ผมพบเป็นธรรมดา
พอล

1
ปรับปรุง: วิธีนี้ได้รับการล้าสมัยในขณะนี้ในความโปรดปรานของ(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt

@ArthurUlfeldt คุณอาจต้องการอัปเดตคำตอบของคุณเพื่อรวม (pun) สิ่งนี้
bfontaine

20

ดังที่ได้กล่าวไปแล้วความแตกต่างที่สำคัญก็คือเมื่อ(require 'foo)คุณอ้างถึงชื่อในเนมสเปซของ lib เช่น(foo/bar ...)ถ้าคุณทำ(use 'foo)ตอนนี้พวกเขาจะอยู่ในเนมสเปซปัจจุบันของคุณ (ไม่ว่าจะเป็นอะไรก็ตาม (bar ...)พวกเขาชอบ

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