differenza tra uso e richiesta


155

Qualcuno può spiegare la differenza tra usee require, sia quando usato direttamente sia come :usee :requirenella nsmacro?


2
Vedi anche stackoverflow.com/questions/10358149/… per quanto riguarda la macro ns; in clojure 1.4 ti suggeriamo di usare: richiedi preferibilmente a: usa
Korny

Risposte:


101

requirecarica le librerie (che non sono già state caricate), usefa lo stesso e fa riferimento ai loro spazi dei nomi con clojure.core/refer(quindi hai anche la possibilità di usare :excludeetc come con clojure.core/refer). Entrambi sono raccomandati per l'uso nspiuttosto che direttamente.


3
Se ho bisogno di lib foo, quindi per usare bar in foo, dovrei scrivere foo / bar ogni volta, giusto? Perché dovresti voler caricare una lib in ns ma non farne riferimento in ns? Immagino che potresti essere preoccupato per le collisioni e non vuoi preoccuparti di doverle riconciliare, giusto?
Jegschemesch,

12
non è necessario riconciliare le collisioni è un buon punto, e più in generale c'è uno stile di programmazione che dice "gli spazi dei nomi sono una grande idea suonatrice di clacson, dovremmo averne di più" (da "Lo Zen di Python") - quindi ad esempio quello stile raccomanda non usando "using namespace foo;" in C ++, in modo che i lettori e i manutentori del codice non debbano preoccuparsi "da dove provenga questa barra", ma vedi invece una foo :: bar più esplicita. request (vs use) supporta questo stile di "spazi dei nomi espliciti".
Alex Martelli,

2
Alex dà una risposta buona ma obsoleta. Come sottolineato da @overthink di seguito, dopo che questa risposta è stata data, il clojure idiomatico raccomanda un uso eccessivo. vedi: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper

Sebbene questa sia la risposta accettata e più votata, è vecchia e rappresenta una visione obsoleta. La risposta migliore è che da @rzv: stackoverflow.com/a/16429572/172272
Didier A.

65

È idiomatico includere funzioni esterne con requiree refer. Si evitano conflitti nello spazio dei nomi, si includono solo le funzioni effettivamente utilizzate / necessarie e si dichiara esplicitamente la posizione di ciascuna funzione:

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

Non devo invocare questa funzione anteponendola con il suo spazio dei nomi:

(wrap-reload) ; works

Se non lo usi, referdevi aggiungere il prefisso allo spazio dei nomi:

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

Se useinvece scegli , (praticamente) usa sempre only:

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

Altrimenti stai includendo tutto, rendendolo un'operazione inutilmente grande e molto confusa per gli altri programmatori per trovare dove vivono le funzioni.

Consiglio vivamente questo blog come risorsa per saperne di più sugli spazi dei nomi Clojure.


Sai se c'è qualche differenza alla fine tra (:use foo :only [bar])e (:require foo :refer [bar])? Sembra strano avere due modi per farlo.
ripensare il

10
Sembra che stackoverflow.com/a/10370672/69689 risponda alla mia domanda. In breve: (:require .. :refer ..)è un nuovo modo di fare la stessa cosa che ti consente di deprecare efficacemente :use, con alcuni inconvenienti.
ripensare il

Buoni esempi. Adoro gli esempi, questo ha molto senso.
Astrid,

35

L'uso sicuro rende più semplice non richiedendo di precisare lo spazio dei nomi ogni volta che si desidera chiamare una funzione, sebbene possa anche creare confusione creando conflitti tra spazi dei nomi. Una buona via di mezzo tra "usa" e "richiede" è di "usare" solo le funzioni di uno spazio dei nomi che effettivamente usi.

per esempio:

 (usa '[clojure-contrib.duck-streams: only (writer reader)])
o ancora meglio, specificalo nella parte superiore del file nella definizione dello spazio dei nomi:

(ns com.me.project
   (: usa [clojure.contrib.test-is: only (deftest is run-test)]))

3
Grazie per aver incluso (pun) la (ns ...)sintassi; Lo stavo cercando, ma tutti gli esempi che ho trovato erano chiari (use ...).
paul

1
AGGIORNAMENTO: questo metodo è ormai obsoleto a favore di(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt,

@ArthurUlfeldt Potresti voler aggiornare la tua risposta per includerla (gioco di parole).
bfontaine,

20

Come è stato detto, la grande differenza è che (require 'foo), quindi, fai riferimento ai nomi nello spazio dei nomi della lib in questo modo: (foo/bar ...)se lo fai (use 'foo), ora sono nel tuo spazio dei nomi attuale (qualunque cosa sia e purché non ci siano conflitti) e puoi chiamare a loro piace (bar ...).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.