différence entre utiliser et exiger

155

Quelqu'un peut-il expliquer la différence entre useet require, à la fois lorsqu'il est utilisé directement et au fur :useet à mesure :requiredans la nsmacro?

Jegschemesch
la source
2
Voir aussi stackoverflow.com/questions/10358149/… en ce qui concerne la macro ns; dans clojure 1.4, il est suggéré d'utiliser: require de préférence à: use
Korny

Réponses:

101

requirecharge les bibliothèques (qui ne sont pas déjà chargées), usefait la même chose et fait référence à leurs espaces de noms avec clojure.core/refer(vous avez donc également la possibilité d'utiliser :excludeetc. comme avec clojure.core/refer). Les deux sont recommandés pour une utilisation dans nsplutôt que directement.

Alex Martelli
la source
3
Si j'ai besoin de lib foo, alors pour utiliser bar dans foo, je devrais écrire foo / bar à chaque fois, non? Pourquoi voudriez-vous charger une bibliothèque dans ns mais ne pas la référencer dans le ns? Je suppose que vous vous inquiétez peut-être des collisions et que vous ne voulez pas vous soucier de les réconcilier, non?
Jegschemesch
12
ne pas avoir à réconcilier les collisions est un bon point, et plus généralement il y a un style de programmation qui dit "les espaces de noms sont une excellente idée, nous devrions en avoir plus" (de "Le Zen de Python") - donc par exemple ce style recommande ne pas utiliser "using namespace foo;" en C ++, pour que les lecteurs et les responsables du code n'aient pas à s'inquiéter de "d'où vient cette barre" mais voient plutôt un toto :: bar plus explicite. require (vs use) prend en charge ce style "d'espaces de noms explicites".
Alex Martelli
2
Alex donne une bonne réponse mais dépassée. Comme @overthink le souligne ci-dessous, après que cette réponse ait été donnée, clojure idiomatique recommande d'exiger une utilisation excessive. voir: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper
Bien que ce soit la réponse acceptée et la plus votée, elle est ancienne et représente une vue dépassée. La meilleure réponse est celle de @rzv: stackoverflow.com/a/16429572/172272
Didier A.
65

Il est idiomatique d'inclure des fonctions externes avec requireet refer. Vous évitez les conflits d'espace de noms, vous n'incluez que les fonctions que vous utilisez réellement / dont vous avez réellement besoin et vous déclarez explicitement l'emplacement de chaque fonction:

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

Je n'ai pas besoin d'appeler cette fonction en la préfixant avec son espace de noms:

(wrap-reload) ; works

Si vous ne l'utilisez pas, refervous devrez le préfixer avec l'espace de noms:

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

Si vous choisissez à la useplace, utilisez (à peu près) toujours only:

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

Sinon, vous incluez tout, ce qui en fait à la fois une opération inutilement volumineuse et très déroutante pour les autres programmeurs de trouver où se trouvent les fonctions.

En outre, je recommande vivement ce blog comme ressource pour en savoir plus sur les espaces de noms Clojure.

rzv
la source
Savez-vous s'il y a une différence à la fin entre (:use foo :only [bar])et (:require foo :refer [bar])? Cela semble étrange d'avoir deux façons de faire cela.
Overhink
10
On dirait que stackoverflow.com/a/10370672/69689 répond à ma question. En bref: (:require .. :refer ..)c'est une nouvelle façon de faire la même chose qui vous permet de déprécier efficacement :use, ce qui présente quelques inconvénients.
Refuser le
Bon donnant des exemples. J'adore les exemples, cela avait beaucoup de sens.
Astrid
35

Utiliser sure facilite les choses en ne vous obligeant pas à épeler l'espace de noms à chaque fois que vous voulez appeler une fonction, bien que cela puisse aussi faire un désordre en créant des conflits d'espace de noms. Un bon compromis entre «utiliser» et «exiger» est de n'utiliser que les fonctions d'un espace de noms que vous utilisez réellement.

par exemple:

 (utilisez '[clojure-contrib.duck-streams: only (writer reader)])
ou mieux encore, spécifiez-le en haut du fichier dans la définition de l'espace de noms:

(ns com.me.project
   (: use [clojure.contrib.test-is: only (deftest est run-tests)]))
Arthur Ulfeldt
la source
3
Merci d'avoir inclus (jeu de mots) la (ns ...)syntaxe; J'avais cherché cela, mais tous les exemples que j'ai trouvés étaient simples (use ...).
paul
1
MISE À JOUR: cette méthode est maintenant obsolète en faveur de(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt
@ArthurUlfeldt Vous voudrez peut-être mettre à jour votre réponse pour inclure (jeu de mots) ceci.
bfontaine
20

Comme cela a été mentionné, la grande différence est qu'avec (require 'foo), vous faites alors référence aux noms dans l'espace de noms de la lib comme ceci: (foo/bar ...)si vous le faites, (use 'foo)ils sont maintenant dans votre espace de noms actuel (quoi qu'il en soit et à condition qu'il n'y ait pas de conflit) et vous pouvez appeler eux aiment (bar ...).

Chris
la source