diferencia entre uso y requiere

155

¿Alguien puede explicar la diferencia entre usey require, tanto cuando se usa directamente como como :usey :requireen la nsmacro?

Jegschemesch
fuente
2
Consulte también stackoverflow.com/questions/10358149/… con respecto a la macro ns; en clojure 1.4 se sugiere que use: requiera con preferencia: use
Korny

Respuestas:

101

requirecarga las bibliotecas (que aún no están cargadas), usehace lo mismo y se refiere a sus espacios de nombres con clojure.core/refer(por lo que también tiene la posibilidad de usar, :excludeetc., como con clojure.core/refer). Ambos se recomiendan para su uso en nslugar de directamente.

Alex Martelli
fuente
3
Si necesito lib foo, entonces para usar bar in foo, tendría que escribir foo / bar cada vez, ¿verdad? ¿Por qué querrías cargar una lib en ns pero luego no referirla a ns? Supongo que puede estar preocupado por las colisiones, y no quiere molestarse en reconciliarlas, ¿verdad?
Jegschemesch
12
no tener que conciliar las colisiones es un buen punto, y en general hay un estilo de programación que dice que "los espacios de nombres son una gran idea para tocar la bocina, deberíamos tener más" (de "The Zen of Python"), por lo que ese estilo recomienda no usar "usar el espacio de nombres foo"; en C ++, para que los lectores y mantenedores del código no tengan que preocuparse "de dónde viene esta barra", sino que verán un foo :: bar más explícito. require (vs use) admite este estilo de "espacios de nombres explícitos".
Alex Martelli
2
Alex da una buena pero anticuada respuesta. Como @overthink señala a continuación, después de dar esta respuesta, clojure idiomático recomienda requerir un uso excesivo. ver: dev.clojure.org/jira/browse/CLJ-879
Phil Cooper
Si bien esta es la respuesta aceptada y más votada, es antigua y representa una vista desactualizada. La mejor respuesta es la de @rzv: stackoverflow.com/a/16429572/172272
Didier A.
65

Es idiomático incluir funciones externas con requirey refer. Evita conflictos de espacio de nombres, solo incluye funciones que realmente usa / necesita, y declara explícitamente la ubicación de cada función:

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

No tengo que invocar esta función con el prefijo con su espacio de nombres:

(wrap-reload) ; works

Si no lo usa refer, necesitará ponerle el prefijo con el espacio de nombres:

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

Si eliges en su uselugar, (más o menos) siempre usa only:

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

De lo contrario, está incluyendo todo, lo que lo convierte en una operación innecesariamente grande y muy confusa para que otros programadores encuentren dónde viven las funciones.

Además, recomiendo este blog como un recurso para aprender más sobre los espacios de nombres de Clojure.

rzv
fuente
¿Sabes si hay alguna diferencia al final entre (:use foo :only [bar])y (:require foo :refer [bar])? Parece extraño tener dos formas de hacer esto.
pensar demasiado el
10
Parece que stackoverflow.com/a/10370672/69689 responde mi pregunta. En resumen: (:require .. :refer ..)es una nueva forma de hacer lo mismo que le permite desaprobar efectivamente :use, lo que tiene algunos inconvenientes.
pensar demasiado el
Bien dando ejemplos. Me encantan los ejemplos, esto tiene mucho sentido.
Astrid
35

El uso seguro hace que sea más fácil al no requerir que deletree el espacio de nombres cada vez que desee llamar a una función, aunque también puede causar problemas creando conflictos de espacio de nombres. Un buen término medio entre "usar" y "requerir" es solo "usar" las funciones de un espacio de nombres que realmente usa.

por ejemplo:

 (use '[clojure-contrib.duck-streams: only (escritor lector)])
o incluso mejor, especifíquelo en la parte superior del archivo en la definición del espacio de nombres:

(ns com.me.project
   (: use [clojure.contrib.test-is: only (deftest es run-tests)]))
Arthur Ulfeldt
fuente
3
Gracias por incluir (juego de palabras) la (ns ...)sintaxis; Había estado buscando eso, pero todos los ejemplos que encontré eran simples (use ...).
Paul
1
ACTUALIZACIÓN: este método ha quedado obsoleto ahora a favor de(require '[namepase :refer [var-name1 var-name2]])
Arthur Ulfeldt
@ArthurUlfeldt Es posible que desee actualizar su respuesta para incluir (juego de palabras) esto.
bfontaine
20

Como se ha mencionado, la gran diferencia es que con (require 'foo), luego se refiere a los nombres en el espacio de nombres de la biblioteca de la siguiente manera: (foo/bar ...)si lo hace (use 'foo), ahora están en su espacio de nombres actual (sea lo que sea y siempre que no haya conflictos) y puede llamar como ellos (bar ...).

Chris
fuente