Macros 有没有一种干净的方法可以将函数添加到动态创建的命名空间中?

Macros 有没有一种干净的方法可以将函数添加到动态创建的命名空间中?,macros,clojure,lisp,noir,Macros,Clojure,Lisp,Noir,我正在创建一个noir webapp,我需要动态创建新的视图和模型。我一直在遵循noir示例,其中资源的视图和控制器具有单独的名称空间,我发现这是一种非常干净的方法 为此,我需要能够动态创建与视图和模型对应的新名称空间,然后在其中插入适当的函数。我的想法是在一个单独的名称空间中指定宏,当在新名称空间中调用宏时,它将提供适当的路由/部分/任何内容 例如(请原谅我的第一个defmacro): 是从 (ns project.proto (:use [clojure.contrib.with-ns

我正在创建一个noir webapp,我需要动态创建新的视图和模型。我一直在遵循noir示例,其中资源的视图和控制器具有单独的名称空间,我发现这是一种非常干净的方法

为此,我需要能够动态创建与视图和模型对应的新名称空间,然后在其中插入适当的函数。我的想法是在一个单独的名称空间中指定宏,当在新名称空间中调用宏时,它将提供适当的路由/部分/任何内容

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

是从

(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。我非常感谢任何帮助,无论是否有更好的方法。比如,只使用refer来表示包含所有必要定义的名称空间


第一篇文章,我不认为这是重复的。谢谢

首先,这个问题已经有点过时了。在过去的一年里,黑葡萄酒和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
我认为这与您最初的示例非常接近


希望这有帮助

你会考虑编辑你的文章,并引用你的名字空间和一些调用宏的示例代码吗?我想看看它是在什么环境下使用的。tnxI希望这会更有帮助。我遇到的错误是无法解决symbol:在这个上下文中使用ns进行编译,但我不知道这是否意味着您可以在函数或宏之外使用ns。在阅读了ns文档之后,我不确定为什么要同时使用create ns和intern。intern将添加到您已经声明的名称空间中,但我仍然不知道为什么with ns显示为无法解析的符号,除非您打算在函数中使用它。clojure contrib中的代码已被弃用且不受支持:在这种情况下,我建议不要使用clojure.contib.with-ns。
$ 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
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"