在Clojure中构建字符串的麻烦

时间:2011-01-08 23:35:09

标签: clojure

[这可能看起来像我的问题是Compojure,但它不是 - 它与Clojure一起]

在这个看似简单的问题上,我一直在拔头发 - 但我无处可去。

我正在使用Compojure(Clojure的轻量级Web框架),我想生成一个显示我的PostgreSQL数据库中的待办事项列表的网页。

下面的代码片段(省略了数据库连接,查询等 - 但不需要该部分,因为特定问题是生成的HTML在< body>和< / body>标记之间没有显示任何内容)

作为测试,我尝试在对main-layout的调用中对字符串进行硬编码,如下所示: (html(主要布局“Aki's Todos”“Haircut< br> Study Clojure< br>回答关于Stackoverfolw的问题”)) - 并且它工作正常。

所以真正的问题是我不相信我知道如何在Clojure中建立一个字符串。不是惯用的方式,也不是通过调用Java的StringBuilder - 正如我在下面的代码中所做的那样。

虚拟啤酒,对任何可以解决它的人来说都是一个很大的支持!非常感谢!

=============================================== ==============


;The master template (a very simple POC for now, but can expand on it later)

(defn main-layout
  "This is one of the html layouts for the pages assets - just like a master page"
  [title body]
  (html
    [:html
    [:head
      [:title title]
      (include-js "todos.js")
      (include-css "todos.css")]
    [:body body]]))


(defn show-all-todos 
  "This function will generate the todos HTML table and call the layout function"
  []
  (let [rs (select-all-todos)
       sbHTML (new StringBuilder)]
    (for [rec rs]
      (.append sbHTML (str rec "<br><br>"))) 
    (html (main-layout "Aki's Todos" (.toString sbHTML)))))

=============================================== ==============

同样,结果是一个网页,但身体标签之间没有任何内容。如果我使用println语句替换for循环中的代码,并将代码指向repl - 忘记网页内容(即调用main-layout),结果集将被打印 - 但是 - 问题在于构建字符串。

再次感谢。

〜秋

2 个答案:

答案 0 :(得分:6)

for是懒惰的,在你的函数中它永远不会被评估。将for更改为doseq

user> (let [rs ["foo" "bar"] 
            sbHTML (new StringBuilder)]
        (for [rec rs]
          (.append sbHTML (str rec "<br><br>")))
        (.toString sbHTML))
""
user> (let [rs ["foo" "bar"] 
            sbHTML (new StringBuilder)]
        (doseq [rec rs]
          (.append sbHTML (str rec "<br><br>")))
        (.toString sbHTML))
"foo<br><br>bar<br><br>"

您还可以使用reduceinterposeclojure.string/join来自clojure.string,或者可能使用其他一些选项。

user> (let [rs ["foo" "bar"]]
            (reduce str (interpose "<br><br>" rs)))
"foo<br><br>bar"
user> (require 'clojure.string)
nil
user> (let [rs ["foo" "bar"]]
            (clojure.string/join "<br><br>" rs))
"foo<br><br>bar"

答案 1 :(得分:2)

您希望像re-gsub这样使用:

(要求'clojure.contrib.str-utils);;请尽快让我们使用re-gsub

(clojure.contrib.str-utils / re-gsub#“\ newline”“&lt; br&gt;&lt; br&gt;”your-string-with-todos-separated-with-newlines)

这最后一行会产生你喜欢的字符串。正如您可能已经知道的那样,require-part可以让编译器访问功能强大的clojure.contrib.str-utils库,而无需将其导入当前命名空间(这可能会导致程序增长时发生不必要的冲突)。

返回reg-exp,并允许你定义一个#“regexp”形式的reg-exp,用于替换所有后续使用参数的regexp命中的实例,应用于第三个参数。在这种情况下,\ newline是在regexp中表示换行符的方式,以及字符串和我们正在寻找的字符。

我认为你真正想做的是用html格式制作一个漂亮的有序或无序列表。这些可以通过[hiccup-page-helpers] [2]完成(如果你没有它们,你可能有一个组件,从它被分解为compojure,打嗝等等,因为你使用html函数)。

如果你想使用hiccup-page-helpers,请以这种方式使用上面提到的clojure.contrib.str-utils中的命令重新拆分:

(使用'hiccup.page-helpers);;注意命名空间冲突,因为hiccup.page-helpers中的所有函数都进入了当前的命名空间。

(unordered-list(clojure.contrib.str-utils / re-split#“\ newline”your-string-with-todos-separated-with-newlines))

哪个应该整洁
&LT; UL&GT;
&LT;李&GT;待办事项-ITEM1和LT; /锂&GT;
&LT;李&GT;待办事项-ITEM2&LT; /锂&GT;
&LT; / UL&GT;

(是的,有一个order-list命令以相同的方式工作!)

在上面的clojure代码的最后一行中,你所有的todos都进入了一个(列表“todo1”“todo2”),它被hiccup.page-helpers unordered-list函数立即使用,并且转换为html-ized列表。

祝好朋友和朋友们好运!