diferença entre usar e exigir

155

Alguém pode explicar a diferença entre usee require, quando usado diretamente e como :usee :requirena nsmacro?

Jegschemesch
fonte
2
Consulte também stackoverflow.com/questions/10358149/… com relação à macro ns; em Clojure 1.4 é sugerido que você usa: exigem por preferência: uso
Korny

Respostas:

101

requirecarrega libs (que ainda não foram carregadas), usefaz o mesmo e se refere aos seus namespaces com clojure.core/refer(para que você também tenha a possibilidade de usar :excludeetc como em clojure.core/refer). Ambos são recomendados para uso em nsvez de diretamente.

Alex Martelli
fonte
3
Se eu precisar de lib foo, para usar bar in foo, eu precisaria escrever foo / bar toda vez, certo? Por que você deseja carregar uma lib em ns, mas não a encaminha para os ns? Acho que você pode estar preocupado com colisões e não quer se incomodar em reconciliá-las, certo?
Jegschemesch
12
não ter que reconciliar colisões é um bom argumento e, geralmente, existe um estilo de programação que diz que "namespaces são uma ótima idéia, devemos ter mais" (de "The Zen of Python") - por exemplo, esse estilo recomenda não usando "using namespace foo;" em C ++, para que os leitores e mantenedores do código não precisem se preocupar "de onde vem essa barra", mas ver um foo :: bar mais explícito. require (vs use) suporta esse estilo "namespaces explícitos".
Alex Martelli
2
Alex dá uma resposta boa, mas desatualizada. Como o @overthink aponta abaixo, depois que essa resposta foi dada, o clojure idiomático recomenda o uso excessivo. Veja: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper
Embora esta seja a resposta aceita e mais votada, ela é antiga e representa uma visão desatualizada. A melhor resposta é que a partir @rzv: stackoverflow.com/a/16429572/172272
Didier A.
65

É idiomático incluir funções externas com requiree refer. Você evita conflitos de espaço para nome, inclui apenas funções que realmente usa / precisa e declara explicitamente o local de cada função:

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

Não preciso chamar essa função prefixando-a com seu espaço para nome:

(wrap-reload) ; works

Se você não usar, referprecisará prefixar o espaço para nome:

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

Se você escolher use, (praticamente) sempre use only:

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

Caso contrário, você está incluindo tudo, tornando-a uma operação desnecessariamente grande e muito confusa para outros programadores descobrirem onde estão as funções.

Além disso, eu recomendo este blog como um recurso para aprender mais sobre os namespaces do Clojure.

rzv
fonte
Você sabe se existe alguma diferença no final entre (:use foo :only [bar])e (:require foo :refer [bar])? Parece estranho ter duas maneiras de fazer isso.
overthink
10
Parece que stackoverflow.com/a/10370672/69689 responde à minha pergunta. Resumindo: (:require .. :refer ..)é uma nova maneira de fazer a mesma coisa que permite que você efetue a depreciação :use, o que tem algumas desvantagens.
overthink
Bons exemplos. Eu amo exemplos, isso fez muito sentido.
Astrid
35

Certifique-se de tornar mais fácil, não exigindo que você soletre o espaço para nome toda vez que quiser chamar uma função, mas também pode causar uma confusão, criando conflitos no espaço para nome. Um bom meio termo entre "use" e "require" é apenas 'usar' as funções de um espaço para nome que você realmente usa.

por exemplo:

 (use '[clojure-contrib.duck-streams: only (escritor escritor)])
ou melhor ainda, especifique-o na parte superior do arquivo na definição de namespace:

(ns com.me.project
   (: use [clojure.contrib.test-is: only (deftest é executar testes)]))
Arthur Ulfeldt
fonte
3
Obrigado por incluir (trocadilho) a (ns ...)sintaxe; Eu estava procurando por isso, mas todos os exemplos que encontrei foram claros (use ...).
paul
1
ATUALIZAÇÃO: este método foi obsoleto agora em favor de(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt
@ArthurUlfeldt Você pode querer atualizar sua resposta para incluir isso.
Bfontaine
20

Como já foi mencionado, a grande diferença é que (require 'foo), com , você se refere a nomes no espaço de nomes da biblioteca da seguinte forma: (foo/bar ...)se o fizer (use 'foo), eles estarão agora no seu espaço de nomes atual (o que quer que seja e desde que não haja conflitos) e você pode chamar eles gostam (bar ...).

Chris
fonte