2012-04-22 14 views
11

Tôi đang tạo một ứng dụng web noir và tôi cần phải tạo động các chế độ xem và mô hình mới. Tôi đã theo dõi các ví dụ noir, trong đó quan điểm và bộ điều khiển cho một tài nguyên có các không gian tên riêng biệt, và tôi đã tìm thấy nó là một cách tiếp cận rất sạch sẽ.Có cách nào sạch sẽ để thêm chức năng vào không gian tên được tạo động không?

Để phù hợp với điều này, tôi cần có khả năng tự động tạo các không gian tên mới tương ứng với lượt xem và mô hình, sau đó thực hiện các chức năng thích hợp trong chúng. Ý tưởng của tôi là có các macro được chỉ định trong một không gian tên riêng biệt, khi được gọi trong không gian tên mới, sẽ cung cấp các tuyến/partials thích hợp/bất cứ điều gì.

Ví dụ (tha thứ defmacro đầu tiên của tôi):

(ns project.views.proto 
    (:use noir.core 
     hiccup.core 
     hiccup.element 
     hiccup.form)) 

(defmacro def-all-page 
    [path] 
    `(defpage ~path [] 
    (html 
     [:h1 "Ya'll here"]))) 

được gọi từ ...

(ns project.proto 
    (:use [clojure.contrib.with-ns :only [with-ns]]) 

(create-ns 'foo) 
(intern 'foo 'path "path") ; In reality, the path is dynamic which is why I intern it 
(with-ns 'foo 
    (clojure.core/refer-clojure) 
    (use 'noir.core 
     'hiccup.core 
     'hiccup.element 
     '[project.views.proto :only [def-all-page]]) 

    (def-all-page path) 

Tuy nhiên, kêu gọi này từ bên trong không gian tên mới của tôi mang lại cho tôi một NullPointerException. Tôi rất cảm kích sự giúp đỡ, và liệu có hay không có cách tiếp cận tốt hơn. Giống như, chỉ sử dụng tham chiếu cho một không gian tên chứa tất cả các định nghĩa cần thiết?

Bài đăng đầu tiên và tôi không cho rằng đó là sự lặp lại của this. Cảm ơn!

+0

Bạn có cân nhắc chỉnh sửa bài đăng của mình và biểu thị không gian tên của bạn và một số mã mẫu Clojure có chứa macro không? Tôi muốn thấy trong bối cảnh nó được sử dụng. tnx – octopusgrabbus

+1

Tôi hy vọng điều đó hữu ích hơn một chút. – jtmoulia

+0

Lỗi tôi nhận được là Không thể phân giải biểu tượng: với-ns trong ngữ cảnh này, biên dịch, nhưng tôi không biết liệu điều đó có nghĩa là bạn có thể sử dụng với các-n bên ngoài một hàm hoặc macro. – octopusgrabbus

Trả lời

1

Trước hết, câu hỏi này đã trở nên lỗi thời một chút. Cả Noir và Clojure đã phát triển trong năm qua. Vì mục đích rõ ràng, tôi sẽ đưa Noir ra khỏi phương trình và cố gắng trả lời câu hỏi của bạn về chức năng tạo động bằng cách sử dụng macro.

theo cùng tại REPL:

$ lein repl 
user=> (in-ns 'foo) 
#<Namespace foo> 
foo=> (clojure.core/refer-clojure) 
nil 
foo=> (defmacro say-hello-to 
#_=>   [name] 
#_=>   `(defn ~(symbol (str "hello-" name)) 
#_=>     [] 
#_=>     ~(str "hello: " name))) 
#'foo/say-hello-to 

Ở đây chúng ta tạo ra một không gian tên 'foo' có chứa một macro để xác định chức năng 'hello-tenban'. Hãy tạo không gian tên khác:

foo=> (in-ns 'bar) 
#<Namespace bar> 
bar=> (clojure.core/refer-clojure) 
nil 
bar=> (refer 'foo :only '[say-hello-to]) 
nil 
bar=> (say-hello-to "tom") 
#'bar/hello-tom 
bar=> (say-hello-to "jerry") 
#'bar/hello-jerry 

Hãy xem nếu những thực sự làm việc:

bar=> (hello-tom) 
"hello: tom" 
bar=> (hello-jerry) 
"hello: jerry" 

Tôi nghĩ rằng đây là khá gần với ví dụ ban đầu của bạn.

Hy vọng điều này sẽ hữu ích!