Unterschied zwischen Verwendung und Anforderung

155

Kann jemand den Unterschied zwischen useund erklären require, sowohl bei direkter Verwendung als auch als :useund :requireim nsMakro?

Jegschemesch
quelle
2
Siehe auch stackoverflow.com/questions/10358149/… bezüglich des ns-Makros; In Clojure 1.4 wird empfohlen, Folgendes zu verwenden: Vorzugsweise benötigen: Verwenden
Korny

Antworten:

101

requireLädt Bibliotheken (die noch nicht geladen sind), usemacht dasselbe und verweist auf deren Namespaces mit clojure.core/refer(so dass Sie auch die Möglichkeit haben, :excludeetc wie mit zu verwenden clojure.core/refer). Beide werden nseher zur Verwendung als direkt empfohlen .

Alex Martelli
quelle
3
Wenn ich lib foo benötige, müsste ich jedes Mal foo / bar schreiben, um bar in foo zu verwenden, oder? Warum sollten Sie eine Bibliothek in ns laden wollen, sie dann aber nicht in die ns verweisen? Ich denke, Sie könnten sich Sorgen um Kollisionen machen und möchten sich nicht die Mühe machen, sie miteinander in Einklang zu bringen, oder?
Jegschemesch
12
Kollisionen nicht in Einklang bringen zu müssen, ist ein guter Punkt, und im Allgemeinen gibt es einen Programmierstil, der besagt, dass "Namespaces eine großartige Idee sind, wir sollten mehr davon haben" (aus "The Zen of Python") - also z. B. empfiehlt dieser Stil nicht "using namespace foo;" in C ++, damit sich Leser und Betreuer des Codes keine Sorgen machen müssen, "woher kommt diese Leiste", sondern stattdessen eine explizitere foo :: bar sehen. require (vs use) unterstützt diesen "expliziten Namespaces" -Stil.
Alex Martelli
2
Alex gibt eine gute, aber veraltete Antwort. Wie @overthink weiter unten ausführt, empfiehlt Clojure nach Erteilung dieser Antwort eine übermäßige Verwendung. siehe: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper
Dies ist zwar die akzeptierte und am besten bewertete Antwort, sie ist jedoch alt und repräsentiert eine veraltete Ansicht. Die bessere Antwort ist die von @rzv: stackoverflow.com/a/16429572/172272
Didier A.
65

Es ist idiomatisch, externe Funktionen mit requireund einzuschließen refer. Sie vermeiden Namespace-Konflikte, schließen nur Funktionen ein, die Sie tatsächlich verwenden / benötigen, und Sie deklarieren explizit den Speicherort jeder Funktion:

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

Ich muss diese Funktion nicht aufrufen, indem ich ihr den Namespace voranstelle:

(wrap-reload) ; works

Wenn Sie nicht verwenden refer, müssen Sie ihm den Namespace voranstellen:

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

Wenn Sie usestattdessen wählen , verwenden Sie (so ziemlich) immer only:

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

Andernfalls schließen Sie alles ein, was es für andere Programmierer sowohl unnötig umfangreich als auch sehr verwirrend macht, herauszufinden, wo sich die Funktionen befinden.

Außerdem empfehle ich diesen Blog als Ressource, um mehr über Clojure-Namespaces zu erfahren.

rzv
quelle
Wissen Sie, ob es am Ende einen Unterschied zwischen (:use foo :only [bar])und gibt (:require foo :refer [bar])? Es scheint seltsam, zwei Möglichkeiten zu haben, dies zu tun.
Überdenken
10
Sieht aus wie stackoverflow.com/a/10370672/69689 beantwortet meine Frage. Kurz gesagt: Dies (:require .. :refer ..)ist eine neue Methode, um das Gleiche zu tun, mit der Sie effektiv ablehnen können :use, was einige Nachteile hat.
Überdenken
Gute Beispiele. Ich liebe Beispiele, das hat sehr viel Sinn gemacht.
Astrid
35

Verwenden Sie dies sicher, um es einfacher zu machen, indem Sie den Namespace nicht jedes Mal buchstabieren müssen, wenn Sie eine Funktion aufrufen möchten. Es kann jedoch auch zu Problemen führen, indem Namespace-Konflikte entstehen. Ein guter Mittelweg zwischen "use" und "require" besteht darin, nur die Funktionen aus einem Namespace zu "verwenden", den Sie tatsächlich verwenden.

zum Beispiel:

 (benutze '[clojure-Contrib.duck-Streams: nur (Writer Reader)])
oder noch besser, geben Sie es oben in der Datei in der Namespace-Definition an:

(ns com.me.project
   (: benutze [clojure.contrib.test-is: only (Geschicklichkeit ist Run-Tests)]))
Arthur Ulfeldt
quelle
3
Vielen Dank, dass Sie die (ns ...)Syntax (Wortspiel) eingefügt haben. Ich hatte danach gesucht, aber alle Beispiele, die ich fand, waren einfach (use ...).
Paul
1
UPDATE: Diese Methode wurde jetzt zugunsten von(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt
@ArthurUlfeldt Möglicherweise möchten Sie Ihre Antwort aktualisieren, um dies einzuschließen (Wortspiel).
Bfontaine
20

Wie bereits erwähnt, besteht der große Unterschied darin, dass (require 'foo)Sie sich dann wie folgt auf Namen im Namespace der Bibliothek beziehen: (foo/bar ...)Wenn Sie dies tun (use 'foo), befinden sie sich jetzt in Ihrem aktuellen Namespace (was auch immer das sein mag und vorausgesetzt, es gibt keine Konflikte) und Sie können anrufen sie mögen (bar ...).

Chris
quelle