27 votes

Différence dans Clojure entre l’utilisation et l’exigence

J'ai récemment commencé à apprendre Clojure et je vais avoir un peu de difficulté enveloppant ma tête autour d'espaces de noms. En tant que créateur de Clojure dit, les nouveaux arrivants ont souvent du mal à obtenir le concept de droit. Je ne pas bien comprendre la différence entre (use ...) et (require ...). Par exemple, à jouer dans le REPL si je dis (use 'clojure.contrib.str-utils2) - je obtenir des avertissements sur les fonctions de clojure.de base de l'espace de noms étant remplacés par ceux en clojure.contrib.str-utils2, mais cela ne se produit pas lorsque j'utilise (require 'clojure.contrib.str-utils2). Je ne suis pas sûr que j'aurai toujours envie de remplacer ce qui est en clojure.de base, donc quelqu'un peut-il point un certain nombre de meilleures pratiques pour importer des trucs et gestion des espaces de noms en Clojure?

Oh, et aussi, quand dois-je utiliser :use et :require? Seulement à l'intérieur d' (ns ....)?

Merci à l'avance.

41voto

Rayne Points 14518

La réponse se trouve dans les docstrings:

user> (doc use)
-------------------------
clojure.core/use
([& args])
  Like 'require, but also refers to each lib's namespace using
  clojure.core/refer. Use :use in the ns macro in preference to calling
  this directly.

  'use accepts additional options in libspecs: :exclude, :only, :rename.
  The arguments and semantics for :exclude, :only, and :rename are the same
  as those documented for clojure.core/refer.
nil

Et à la longue pour exiger:

user> (doc require)
-------------------------
clojure.core/require
([& args])
  Loads libs, skipping any that are already loaded. Each argument is
  either a libspec that identifies a lib, a prefix list that identifies
  multiple libs whose names share a common prefix, or a flag that modifies
  how all the identified libs are loaded. Use :require in the ns macro
  in preference to calling this directly.

  Libs

  A 'lib' is a named set of resources in classpath whose contents define a
  library of Clojure code. Lib names are symbols and each lib is associated
  with a Clojure namespace and a Java package that share its name. A lib's
  name also locates its root directory within classpath using Java's
  package name to classpath-relative path mapping. All resources in a lib
  should be contained in the directory structure under its root directory.
  All definitions a lib makes should be in its associated namespace.

  'require loads a lib by loading its root resource. The root resource path
  is derived from the lib name in the following manner:
  Consider a lib named by the symbol 'x.y.z; it has the root directory
  <classpath>/x/y/, and its root resource is <classpath>/x/y/z.clj. The root
  resource should contain code to create the lib's namespace (usually by using
  the ns macro) and load any additional lib resources.

  Libspecs

  A libspec is a lib name or a vector containing a lib name followed by
  options expressed as sequential keywords and arguments.

  Recognized options: :as
  :as takes a symbol as its argument and makes that symbol an alias to the
    lib's namespace in the current namespace.

  Prefix Lists

  It's common for Clojure code to depend on several libs whose names have
  the same prefix. When specifying libs, prefix lists can be used to reduce
  repetition. A prefix list contains the shared prefix followed by libspecs
  with the shared prefix removed from the lib names. After removing the
  prefix, the names that remain must not contain any periods.

  Flags

  A flag is a keyword.
  Recognized flags: :reload, :reload-all, :verbose
  :reload forces loading of all the identified libs even if they are
    already loaded
  :reload-all implies :reload and also forces loading of all libs that the
    identified libs directly or indirectly load via require or use
  :verbose triggers printing information about each load, alias, and refer

  Example:

  The following would load the libraries clojure.zip and clojure.set
  abbreviated as 's'.

  (require '(clojure zip [set :as s]))
nil

Ils font tous les deux la même chose, mais use va plus loin et crée des correspondances pour les trucs dans le besoin avait de l'espace de noms dans l'espace de noms courant. De cette façon, plutôt que de faire de l' some.namespace/name vous êtes tout simplement référence à elle comme name. Alors que c'est pratique parfois, il est préférable d'utiliser exiger ou de sélectionner les revendeurs à valeur ajoutée qui vous voulez, plutôt que de le tirer dans l'ensemble de l'espace de noms. Sinon, vous pourriez avoir des problèmes avec ombrage (où l'on var est préféré à un autre du même nom).

Si vous ne souhaitez pas l'utiliser, mais vous savez ce que vars vous voulez de l'espace de noms, vous pouvez faire ceci:

(ns whatever
  (:use [some.namespace :only [vars you want]]))

Si vous ne savez pas qui vars, vous allez avoir besoin, ou si vous avez besoin d'un lot, il est préférable d'utiliser l'exigent. Même lorsque vous avez besoin, vous n'avez toujours pas de taper le nom totalement qualifié. Vous pouvez faire ceci:

(ns whatever
  (:require [some.namespace :as sn]))

et puis vous pouvez utiliser vars pour certains.espace de noms comme ceci: (sn/somefunction arg1 arg2)

Et pour répondre à votre dernière question: essayez d'utiliser seulement :besoin et :utilisation à l'intérieur de ns ( ... ). C'est beaucoup plus propre de cette façon. N' use et require à l'extérieur de (ns ..), sauf si vous avez une assez bonne raison pour cela.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X