різниця між використанням та потребою


155

Може хто - небудь пояснити різницю між useі require, як при використанні безпосередньо і , як :useі :requireв nsмакро?


2
Дивіться також stackoverflow.com/questions/10358149/… щодо макросу ns; в clojure 1.4 пропонується використовувати: вимагати надати перевагу: використовувати
Корній

Відповіді:


101

requireвантажі ЛІЕС (які ще не завантажені), useробить те ж саме , плюс це відноситься до їх просторів імен з clojure.core/refer(так що ви також отримуєте можливість використання і :excludeт.д. , як з clojure.core/refer). Обидва рекомендується використовувати, nsа не безпосередньо.


3
Якщо мені потрібен lib foo, то для використання bar in foo я повинен писати foo / bar щоразу, правда? Чому ви хочете завантажити ліб в ns, але потім не пересилати його в ns? Я думаю, що ви можете турбуватися про зіткнення, і ви не хочете турбуватися про необхідність їх узгодження, правда?
Джегшемеш

12
не потрібно узгоджувати зіткнення - це сприятливий момент, і в цілому існує стиль програмування, який говорить, що "простори імен - це чудова ідея, ми повинні їх мати більше" (від "Дзен Пітона") - так, наприклад, цей стиль рекомендує не використовується "використання foo простору імен;" в C ++, так що читачам та обслуговуючим кодам не доведеться турбуватися "звідки береться ця панель", а побачити більш чіткий foo :: bar. вимагає (проти використання) підтримує цей стиль "явних просторів імен".
Алекс Мартеллі

2
Олексій дає хорошу, але застарілу відповідь. Як вказує @overthink нижче, після даної відповіді ідіоматична клоджура рекомендує вимагати надмірного використання. дивіться: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper

Хоча це прийнята і найбільш голосована відповідь, вона стара і являє собою застарілий вигляд. Кращою відповіддю є те , що з @rzv: stackoverflow.com/a/16429572/172272
Didier А.

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

Переконайтеся, що це полегшує ситуацію, не вимагаючи, щоб ви прописували простір імен кожного разу, коли ви хочете викликати функцію, хоча це також може створювати безлад, створюючи конфлікти у просторі імен. Хорошим середнім середовищем між "використання" та "вимагати" є лише "використання" функцій з простору імен, які ви фактично використовуєте.

наприклад:

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

(ns com.me.project
   (: використовуйте [clojure.contrib.test-is: only (deftest is run-testing)]))

3
Дякую за включення (каламбур) (ns ...)синтаксису; Я шукав це, але всі знайдені нами приклади були зрозумілими (use ...).
Павло

1
ОНОВЛЕННЯ: цей метод застарів зараз на користь(require '[namepase :refer [var-name1 var-name2]])
Артур Ульфельт

@ArthurUlfeldt Можливо, ви захочете оновити свою відповідь, щоб включити (каламбур) це.
bfontaine

20

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.