Разница между использованием и потребностью


155

Кто-нибудь может объяснить разницу между useи require, как при непосредственном использовании, так и как :useи :requireв nsмакросе?


2
См. Также stackoverflow.com/questions/10358149/… относительно макроса ns; в clojure 1.4 предлагается использовать: требовать по предпочтению: use
— Korny

Ответы:


101

requireзагружает библиотеки (которые еще не загружены), useделает то же самое, плюс к ним относится их пространство имен clojure.core/refer(так что вы также можете использовать и :excludeт.д., как с clojure.core/refer). Оба рекомендуются для использования, nsа не напрямую.


3
Если мне потребуется lib foo, то чтобы использовать bar в foo, мне придется каждый раз писать foo / bar, верно? Почему вы хотите загрузить библиотеку в ns, но не ссылаться на нее в ns? Я думаю, вы можете быть обеспокоены столкновениями, и вы не хотите беспокоиться о необходимости их примирить, верно?
— Jegschemesch

12
отсутствие необходимости согласовывать коллизии - это хороший момент, и в целом существует стиль программирования, который гласит: «Пространства имен - это замечательная идея, у нас их должно быть больше» (из «Дзэн Python») - например, этот стиль рекомендует не используя "использование пространства имен foo;" в C ++, чтобы читатели и сопровождающие кода не беспокоились «откуда взялась эта панель», а вместо этого увидели более явный foo :: bar. require (vs use) поддерживает этот стиль "явных пространств имен".
— Алекс Мартелли

2
Алекс дает хороший, но устаревший ответ. Как @overthink указывает ниже, после того, как этот ответ был дан, идиоматическая clojure рекомендует требовать чрезмерного использования. см .: dev.clojure.org/jira/browse/CLJ-879
— Фил Купер

Несмотря на то, что это принятый и получивший наибольшее количество голосов ответ, он устарел и представляет собой устаревшее мнение. Лучший ответ: @rzv: stackoverflow.com/a/16429572/172272
— Дидье А.

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, что имеет некоторые недостатки.
— переосмыслить

Хорошие примеры. Я люблю примеры, в этом было много смысла.
— Астрид

35

Убедитесь, что это действительно облегчает задачу, не требуя, чтобы вы прописывали пространство имен каждый раз, когда вы хотите вызвать функцию, хотя это также может привести к путанице, создавая конфликты пространства имен. Хорошим промежуточным звеном между «use» и «require» является только «использование» функций из пространства имен, которое вы фактически используете.

например:

 (используйте '[clojure-contrib.duck-streams: only (писатель читатель)])
или, что еще лучше, укажите его в начале файла в определении пространства имен:

(ns com.me.project
   (: использовать [clojure.contrib.test-is: only (deftest является run-tests)]))

3
Спасибо за включение (каламбур) (ns ...)синтаксиса; Я искал это, но все примеры, которые я нашел, были для простого (use ...).
— Павел

1
ОБНОВЛЕНИЕ: этот метод уже устарел в пользу(require '[namepase :refer [var-name1 var-name2]])
— Артур Ульфельдт

@ArthurUlfeldt Вы можете обновить свой ответ, чтобы включить (каламбур) это.
— Бфонтен

20

Как уже упоминалось, большая разница заключается в том (require 'foo), что с помощью этого вы затем ссылаетесь на имена в пространстве имен библиотеки следующим образом: (foo/bar ...)если вы это сделаете, (use 'foo)то они теперь находятся в вашем текущем пространстве имен (что бы это ни было и при условии отсутствия конфликтов), и вы можете вызвать им нравится (bar ...).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.