perbedaan antara penggunaan dan kebutuhan

155

Adakah yang bisa menjelaskan perbedaan antara usedan require, baik ketika digunakan secara langsung dan sebagai :usedan :requiredi nsmakro?

Jegschemesch
sumber
2
Lihat juga stackoverflow.com/questions/10358149/… sehubungan dengan ns macro; di clojure 1.4 disarankan Anda menggunakan: mengharuskan dengan preferensi untuk: menggunakan
Korny

Jawaban:

101

requireload libs (yang belum dimuat), usemelakukan plus yang sama mengacu pada namespace mereka dengan clojure.core/refer(jadi Anda juga mendapatkan kemungkinan menggunakan :excludedll suka dengan clojure.core/refer). Keduanya direkomendasikan untuk digunakan nsdaripada langsung.

Alex Martelli
sumber
3
Jika saya memerlukan lib foo, maka untuk menggunakan bar di foo, saya harus menulis foo / bar setiap waktu, bukan? Mengapa Anda ingin memuat lib dalam ns tetapi kemudian tidak merujuknya ke ns? Saya kira Anda mungkin khawatir tentang tabrakan, dan Anda tidak ingin repot harus mendamaikan mereka, kan?
Jegschemesch
12
tidak harus mendamaikan tabrakan adalah poin yang baik, dan lebih umum ada gaya pemrograman yang mengatakan "namespaces adalah ide besar yang membunyikan klakson, kita harus memiliki lebih dari itu" (dari "The Zen of Python") - jadi misalnya gaya itu merekomendasikan tidak menggunakan "using namespace foo;" di C ++, sehingga pembaca dan pengelola kode tidak perlu khawatir "dari mana bilah ini berasal" tetapi lihat foo :: bar yang lebih eksplisit sebagai gantinya. mengharuskan (vs digunakan) mendukung gaya "ruang nama eksplisit" ini.
Alex Martelli
2
Alex memberikan jawaban yang bagus tapi ketinggalan jaman. Seperti yang ditunjukkan oleh @overthink di bawah ini, setelah jawaban ini diberikan, clojure idiomatis merekomendasikan penggunaan yang berlebihan. lihat: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper
Meskipun ini adalah jawaban yang diterima dan paling banyak dipilih, itu sudah tua dan mewakili pandangan yang sudah ketinggalan zaman. Jawaban yang lebih baik adalah dari @rzv: stackoverflow.com/a/16429572/172272
Didier A.
65

Adalah idiomatis untuk memasukkan fungsi eksternal dengan requiredan refer. Anda menghindari konflik namespace, Anda hanya menyertakan fungsi yang sebenarnya Anda gunakan / butuhkan, dan Anda secara eksplisit menyatakan lokasi masing-masing fungsi:

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

Saya tidak harus menjalankan fungsi ini dengan mengawalinya dengan namespace-nya:

(wrap-reload) ; works

Jika Anda tidak menggunakannya, referAnda harus membuatnya awalan dengan namespace:

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

Jika Anda memilih usesebagai gantinya, (cukup banyak) selalu menggunakan only:

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

Kalau tidak, Anda memasukkan semuanya, menjadikannya sebuah operasi besar yang tidak perlu dan sangat membingungkan bagi programmer lain untuk menemukan di mana fungsinya.

Juga, saya sangat merekomendasikan blog ini sebagai sumber untuk mempelajari lebih lanjut tentang ruang nama Clojure.

rzv
sumber
Apakah Anda tahu jika ada perbedaan pada akhirnya antara (:use foo :only [bar])dan (:require foo :refer [bar])? Tampaknya aneh memiliki dua cara untuk melakukan ini.
terlalu banyak berpikir
10
Sepertinya stackoverflow.com/a/10370672/69689 menjawab pertanyaan saya. Singkatnya: (:require .. :refer ..)adalah cara baru untuk melakukan hal yang sama yang memungkinkan Anda untuk secara efektif terdepresiasi :use, yang memiliki beberapa kelemahan.
overthink
Berikan contoh yang bagus. Saya suka contoh, ini sangat masuk akal.
Astrid
35

Penggunaan tentu membuat lebih mudah dengan tidak mengharuskan Anda untuk mengeja namespace setiap kali Anda ingin memanggil fungsi meskipun itu juga dapat membuat kekacauan dengan menciptakan konflik namespace. Jalan tengah yang baik antara "gunakan" dan "perlu" adalah dengan hanya 'menggunakan' fungsi-fungsi dari namespace yang sebenarnya Anda gunakan.

misalnya:

 (gunakan '[clojure-contrib.duck-stream: only (writer reader)])
atau bahkan lebih baik, tentukan di bagian atas file dalam definisi namespace:

(proyek ns com.me.
   (: gunakan [clojure.contrib.test-is: only (deftest run-tes)]))
Arthur Ulfeldt
sumber
3
Terima kasih telah memasukkan (pun) (ns ...)sintaksis; Saya telah mencari-cari itu tetapi semua contoh yang saya temukan jelas (use ...).
paul
1
UPDATE: metode ini telah usang sekarang mendukung(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt
@ArthurUlfeldt Anda mungkin ingin memperbarui jawaban Anda untuk memasukkan (pun) ini.
bfontaine
20

Seperti telah disebutkan perbedaan besar adalah dengan (require 'foo), Anda kemudian merujuk nama-nama di namespace lib seperti: (foo/bar ...)jika Anda melakukannya (use 'foo)maka mereka sekarang di namespace Anda saat ini (apa pun yang mungkin dan asalkan tidak ada konflik) dan Anda dapat memanggil mereka suka (bar ...).

Chris
sumber