我在Clojure(或者那个问题上的lisp)方面经验很少,而且我已经完成了谷歌和一些试验和错误,但似乎无法理解这种编码风格.
(def smpl2 (ref {"Salaried" [{"John Doe" ["12:00-20:00" nil nil nil "11:00-19:00"]} {"Mary Jane" [nil "12:00-20:00" nil nil nil "11:00-19:00"]}] "Shift Manager" [{"Peter Simpson" ["12:00-20:00" nil nil nil "11:00-19:00"]} {"Joe Jones" [nil "12:00-20:00" nil nil nil "11:00-19:00"]}] "Other" [{"Super Man" ["07:00-16:00" "07:00-16:00" "07:00-16:00" "07:00-16:00" "07:00-16:00"]}]}))
我试图通过这个最初使用然后转移到doseq和最终domap(这似乎更成功)并将内容转储到html表(我的原始python程序从sqlite数据库输出到使用COM的excel电子表格).
这是我的尝试(create-table fn):
(defn html-doc [title & body] (html (doctype "xhtml/transitional") [:html [:head [:title title]] [:body body]])) (defn create-table [] [:h1 "Schedule"] [:hr] [:table (:style "border: 0; width: 90%") [:th "Name"][:th "Mon"][:th "Tue"][:th "Wed"] [:th "Thur"][:th "Fri"][:th "Sat"][:th "Sun"] [:tr (domap [ct @smpl2] [:tr [:td (key ct)] (domap [cl (val ct)] (domap [c cl] [:tr [:td (key c)]]))]) ]]) (defroutes tstr (GET "/" ((html-doc "Sample" create-table))) (ANY "*" 404))
这会输出带有部分(工资,经理等)和章节中的名称的表格,我只是觉得我通过嵌套太多次来滥用domap,因为我可能需要添加更多的domaps才能获得在适当的列和代码中的转换时间对它来说是一种“肮脏”的感觉.
如果我没有提供足够的信息,我会提前道歉,我通常不会在编码方面寻求帮助,这也是我的第一个问题:).
如果你知道任何更好的方法来做到这一点,甚至提示或技巧,我应该知道作为一个新手,他们肯定是受欢迎的.
谢谢.
解决方法
(defn map-tag [tag xs] (map (fn [x] [tag x]) xs)) (defn create-table [] (list [:h1 "Schedule"] [:hr] [:table {:style "border: 0; width: 90%"} [:tr (map-tag :th ["Name" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"])] [:tr (for [[category people] smpl2] (list* [:tr [:td category]] (for [person people [name hours] person] [:tr [:td name] (map-tag :td hours)])))]]))
“在seq上映射并将所有内容包装在同一个标签中”模式很常见,我有时会喜欢使用辅助函数.
Compojure为您扩展了一个seq级别.因此,您可以将一些内容放入列表中,以便在HTML输出中按顺序显示标记,这样我就可以显示h1和hr.在你的代码中,你只是扔掉了h1和hr.
但请注意,它只扩展了一个级别.当你有一个列表列表或一个seq列表时,外部seq将会扩展,但内部seq将不会.
user> (println (html (list [:div "foo"] (for [x [1 2 3]] [:div x])))) <div>foo</div>clojure.lang.LazySeq@ea73bbfd
看看内部seq如何制作Compojure barf.查看compojure.html.gen / expand-seqs以查看其工作原理,或者如果您愿意,可以更改/修复它.
当您在列表中嵌套for或for时,这可能是一个问题,因为返回一个惰性seq.但你必须避免使用seq-in-a-seq.我使用上面的列表*. list和html的组合也可以使用.还有很多其他方法.
user> (println (html (list* [:div "foo"] (for [x [1 2 3]] [:div x])))) <div>foo</div><div>1</div><div>2</div><div>3</div> user> (println (html (list [:div "foo"] (html (for [x [1 2 3]] [:div x]))))) <div>foo</div><div>1</div><div>2</div><div>3</div>