2011-01-19 14 views
15

Tôi nghĩ rằng use sẽ làm điều đó nhưng có vẻ như ánh xạ được tạo trong không gian tên hiện tại không được công khai. Dưới đây là một ví dụ về những gì tôi muốn đạt được:Tôi có thể tham chiếu một không gian tên khác và hiển thị các chức năng của nó như là công khai cho các ns hiện tại không?

(ns my-ns 
    (:use [another-ns :only (another-fct)])) 

(defn my-fct 
    [] 
    (another-fct 123)) ; this works fine 

Sau đó, tôi có một không gian tên như thế này:

(ns my-ns-2 
    (:require [my-ns :as my])) 

(defn my-fct-2 
    [] 
    (my/another-fct 456)) ; this doesn't work 

Tôi muốn làm điều đó vì another-ns là một thư viện để truy cập vào một cơ sở dữ liệu . Tôi muốn cô lập tất cả các cuộc gọi đến thư viện này trong một không gian tên duy nhất (my-ns), theo cách này, tất cả các hàm phụ thuộc DB sẽ được tách biệt trong một không gian tên duy nhất và trở nên dễ dàng chuyển sang DB khác nếu cần.

Một số chức năng của thư viện này chỉ tốt cho tôi nhưng tôi muốn tăng thêm cho người khác. Hãy nói rằng các chức năng đọc là tốt nhưng tôi muốn tăng cường các chức năng ghi với một số xác nhận.

Cách duy nhất tôi thấy cho đến thời điểm này là mã hóa tất cả ánh xạ thành my-ns ngay cả đối với các chức năng tôi không tăng thêm.

Trả lời

8

Liệu sự giúp đỡ này?

(defmacro pull [ns vlist] 
    `(do [email protected](for [i vlist] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

Dưới đây là một ví dụ:

(ns my-ns) 

(defmacro pull [ns vlist] 
    `(do [email protected](for [i vlist] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

(pull clojure.string (reverse replace)) 

(defn my-reverse 
    [] 
    (reverse "abc")) 

(ns my-ns-2) 

(defn my-fct-2 [] 
    (list (my-ns/my-reverse) 
     (my-ns/reverse "abc"))) 

(my-fct-2) 

Nếu bạn muốn chỉ cần kéo trong tất cả mọi thứ, sau đó:

(defmacro pullall [ns] 
    `(do [email protected](for [i (map first (ns-publics ns))] 
      `(def ~i ~(symbol (str ns "/" i)))))) 

(pullall clojure.string) 
+0

Thật tuyệt vời! Tôi đã chuyển dấu chấp nhận cho bạn. Cảm ơn. – Damien

+0

Hmm. Hữu ích, nhưng dường như bị giới hạn ở các không gian tên có chứa các hàm một mình: 'Không thể lấy giá trị của macro '. –

11

Một cách để thực hiện điều này có chọn lọc (chỉ định từng chức năng một cách rõ ràng) là sử dụng một số thứ như số Potemkin library của Zach Tellman. Một ví dụ về việc sử dụng nó được tìm thấy trong không gian tên lamina.core phục vụ như là điểm vào công cộng cho Lamina, nhập khẩu các chức năng công cộng quan trọng từ tất cả các không gian tên nội bộ khác.

Bạn cũng có thể sử dụng clojure.contrib.def/defalias:

(use 'clojure.contrib.def/defalias) 
(defalias foo clojure.string/blank?) 
(foo "") 
+0

Rất hữu ích, cảm ơn rất nhiều. – Damien

+5

Potemkin thật tuyệt vời. Tôi thấy điều này hữu ích hơn câu trả lời được chấp nhận, điều này không hoạt động trên các macro. –

+0

'defalias' là [không thực sự là một bí danh nhưng một bản sao] (https://groups.google.com/d/msg/clojure/LhidPSlvX_Q/mS4R_52suXwJ) – beluchin

1

Để kéo tất cả mọi thứ từ namespace mà có thể có các macro được xác định trong phạm vi sử dụng

này
(defmacro pullall [ns] 
    `(do [email protected](for [[sym var] (ns-publics ns)] 
      `(def ~sym ~var)))) 
Các vấn đề liên quan