2012-04-22 85 views
11

我正在创建一个noir webapp,我需要动态创建新的视图和模型。我一直在关注noir示例,其中资源的视图和控制器具有不同的名称空间,我发现它是一种非常干净的方法。有没有一种干净的方式来添加功能到动态创建的命名空间?

与此相应地,我需要能够动态地创建对应的视图和模型,然后实习生相应的功能在他们新的命名空间。我的想法是在一个单独的命名空间中指定宏,在新的命名空间中调用时,它将提供适当的路由/ partials/whatever。

例如(原谅我的第一个defmacro):

(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"]))) 

从叫...

(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) 

但是,从我的新的命名空间中调用这给了我一个NullPointerException。我非常感谢任何帮助,以及是否有更好的方法。就像,只使用引用包含所有必要定义的名称空间?

第一篇文章,我不认为这是this重演。谢谢!

+0

你会考虑编辑你的文章,并指出你的名字空间和一些调用宏的示例Clojure代码吗?我想看看它在什么情况下使用。 tnx – octopusgrabbus 2012-04-22 22:02:39

+1

我希望这会更有帮助。 – jtmoulia 2012-04-22 22:29:54

+0

我得到的错误是无法解析符号:在此上下文中带-ns编译,但我不知道这是否意味着您可以在函数或宏外使用-NS。 – octopusgrabbus 2012-04-22 22:38:48

回答

1

首先,这个问题已经变得有些过时了。 Noir和Clojure在去年都有进化。为了清楚起见,我将Noir从等式中解释出来,并尝试回答有关使用宏动态创建函数的问题。

在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 

这里我们创建一个命名空间“富”包含宏定义“你好,提供yourname”功能。让我们创建另一个命名空间:

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 

让我们来看看这些实际工作:

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

我觉得这是非常接近你原来的例子。

希望这会有所帮助!

相关问题