2010-08-04 38 views
27

Gần đây tôi đã bắt đầu học Clojure và tôi đang gặp khó khăn trong việc gói đầu của mình quanh các không gian tên. Là tác giả của Clojure, những người mới đến thường đấu tranh để có được khái niệm đúng đắn. Tôi không hiểu rõ sự khác biệt giữa (use ...)(require ...). Ví dụ chơi xung quanh trong REPL nếu tôi nói (use 'clojure.contrib.str-utils2) Tôi nhận được cảnh báo về các chức năng trong không gian tên clojure.core đang được thay thế bằng các hàm trong clojure.contrib.str-utils2, nhưng điều đó không xảy ra khi tôi sử dụng (require 'clojure.contrib.str-utils2). Tôi không chắc chắn rằng tôi sẽ luôn luôn muốn thay thế những gì trong clojure.core, vì vậy ai đó có thể chỉ ra một số thực tiễn tốt nhất để nhập nội dung bên ngoài và quản lý không gian tên trong Clojure?Sự khác biệt trong Clojure giữa việc sử dụng và yêu cầu

Ồ, đồng thời, khi nào tôi nên sử dụng :use:require? Chỉ bên trong (ns ....)?

Xin cảm ơn trước.

+0

bản sao có thể có của [khác biệt giữa sử dụng và yêu cầu] (http://stackoverflow.com/questions/871997/difference-between-use-and-require) –

Trả lời

42

Câu trả lời nằm trong 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 

Và con đường dài cho yêu cầu:

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 

Cả hai đều làm điều tương tự, nhưng use đi thêm bước và tạo ra các ánh xạ cho công cụ trong không gian tên require'd trong không gian tên hiện tại. Bằng cách đó, thay vì làm some.namespace/name, bạn chỉ đề cập đến nó là name. Mặc dù điều này đôi khi thuận tiện, tốt hơn là sử dụng yêu cầu hoặc chọn các vars cá nhân mà bạn muốn thay vì kéo toàn bộ không gian tên. Nếu không, bạn có thể có vấn đề với shadowing (trong đó một var được ưa thích hơn một tên khác).

Nếu bạn không muốn sử dụng đòi hỏi, nhưng bạn biết những gì vars bạn muốn ra khỏi không gian tên, bạn có thể làm điều này:

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

Nếu bạn không biết mà vars bạn đang đi cần, hoặc nếu bạn cần rất nhiều, tốt hơn là sử dụng yêu cầu. Ngay cả khi bạn yêu cầu, bạn không phải luôn luôn gõ tên hoàn toàn đủ điều kiện. Bạn có thể làm điều này:

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

và sau đó bạn có thể sử dụng vars từ some.namespace như thế này: (sn/somefunction arg1 arg2)

Và để trả lời câu hỏi cuối cùng của bạn: cố gắng chỉ sử dụng: yêu cầu và: sử dụng bên trong (ns ...). Nó sạch hơn nhiều theo cách này. Không userequire bên ngoài (ns ..) trừ khi bạn có lý do khá tốt cho nó.

Các vấn đề liên quan