【问题标题】:Binding a local var in deftemplate for enlive在 deftemplate 中绑定本地 var 以进行激活
【发布时间】:2012-08-08 07:22:39
【问题描述】:

我是 clojure 和 Web 开发堆栈的新手。我正在尝试使用 enlive 在 HTML 模板中设置值:

(en/deftemplate project-main-page
  (en/xml-resource "project-main.html")
  [id]
  [:#project-name] (en/content (str "Name: " ((get-project id) :name)))
  [:#project-desc] (en/content (str "Desc: " ((get-project id) :desc))))

这可以很好地设置我的两个 HTML 元素,但它需要重复调​​用我的函数 get-project。目前这只是从本地地图读取,但最终它会涉及一些外部存储访问,所以我宁愿只在这个函数中执行一次。

我正在考虑使用let

(en/deftemplate project-main-page
  (en/xml-resource "project-main.html")
  [id]
  (let [project (get-project id)]
    [:#project-name] (en/content (str "Name: " (project :name)))
    [:#project-desc] (en/content (str "Desc: " (project :desc)))))

但这只会影响描述元素并忽略名称形式。

deftemplate 中绑定本地变量的最佳方法是什么?

【问题讨论】:

  • 尝试在你的deftemplate上运行macroexpand,它可能会提供信息。

标签: clojure enlive


【解决方案1】:

如果我了解您想要达到的目标;您也可以尝试使用 enlive 提供的转换宏。

(defn main-page [{:keys [name desc] :as project}]
 (en/transformation
   [:#project-name] (en/content (str "Name: " name)
   [:#project-desc] (en/content (str "Desc: " desc))))


(en/deftemplate project-main-page
  (en/xml-resource "project-main.html")
  [id]
   (main-page (get-project id)))

代码未经测试,但我希望它传达了一种不同的方式来做你需要的事情

【讨论】:

    【解决方案2】:

    Enlive 的 deftemplate 宏在 args 向量之后需要一系列标签/内容对(在您的示例中,args 向量是 [id])。您不能只在其中粘贴 let,因为宏不期望 let 表单,因此当它进行拼接时,一切都会变得混乱并导致您在上面描述的行为。

    解决此问题的一种方法是编写自己的 deftemplate 宏,该宏允许使用 args 向量中的标识符进行绑定定义。示例:

    (alt/deftemplate project-main-page
      (en/xml-resource "project-main.html")
      [id]
      [project (get-project id)]
      [:#project-name] (en/content (str "Name: " (project :name)))
      [:#project-desc] (en/content (str "Desc: " (project :desc))))
    

    deftemplate 宏是 template 的简单包装,它使用 snippet*,这可能是您需要插入更改的地方:

    (defmacro snippet* [nodes args & forms]
      `(let [nodes# (map annotate ~nodes)]
         (fn ~args
           ; You could add let bindings here since args are in scope
           (doall (flatmap (transformation ~@forms) nodes#)))))
    

    另一个选项(可能更简单,因为您不必在库代码中乱七八糟)是为您的 get-project 函数添加一个间接级别以缓存结果。你可以试试core.cache 库。

    【讨论】:

    • 如果您需要,我已经更新(尽管未经测试)版本的 deftemplatesnippet* 宏,但我不想剥夺您自己进行更改和学习的机会更多关于宏的内容!
    • 谢谢。我还只是刚刚开始学习,还没有完全理解宏语法。我会去看看我能想出什么。
    • 宏一开始有点疯狂,但是一旦你理解了语法引用,它们就不是那么糟糕了。只是不要忘记回来分享你的想法! :D
    猜你喜欢
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多