处理clojure中多个返回值的“正确”方法,其中顺序很重要

时间:2012-07-09 16:23:31

标签: vector clojure

我正在使用打嗝生成一些复选框,后跟标签。原始代码看起来像这样:

(check-box "check1")
(label "check1" "Check1") 
(check-box "check2")
(label "check2" "Check2")
(check-box "check1")
(label "check3" "Check3")
(check-box "check4")
(label "check4" "Check4")

经过大量的修补,我得到了以下几句话:

(map
    (fn [x]
        (map
            #(get (vector
                (check-box x)
                (label x (capitalize x)))%)
            [0 1]))
    ["check1" "check2" "check3" "check4"])

哪个有效,但我觉得我不是在非常类似于/优化/正确的等等。方式 - 特别是返回一个向量只是为了用get来挖出这些值。有更好的方法吗?

3 个答案:

答案 0 :(得分:11)

也许你需要解构?

(defn multi-return-fn []
  [:1 :2 :3])

(let [[x y z] (multi-return-fn)]
    (println x)
    (println y)
    (println z))

解构也适用于fn参数,循环,for循环等。

答案 1 :(得分:5)

正如其他人所说,你的问题不是很清楚,但在正常的Hiccup应用程序的背景下,以下是一个合理的假设你想要的东西:

(apply concat
       (for [boxnum (range 1 5)
             :let [lower-name (str "check" boxnum)
                   upper-name (str "Check" boxnum)]]
         [(check-box lower-name)
          (label lower-name upper-name)]))

还有很多其他方法可以写出来;这个人在冗长而清晰的方面犯了错误,而不是简洁。

答案 2 :(得分:1)

在amalloy评论后编辑

我不知道打嗝,我不完全明白你想要做什么。具体来说,我不明白你要做的那一行的get方面你想要它做什么。但是,您似乎想要从以下代码块中获取返回值列表:

(check-box "check1")
(label "check1" "Check1") 
(check-box "check2")
(label "check2" "Check2")
(check-box "check1")
(label "check3" "Check3")
(check-box "check4")
(label "check4" "Check4")

如果我是对的,那就是你想做的事情,那么最简单的方法 - 但最不通用的方式 - 就是简单地将它全部包装在列表调用中。但是,为了使它更通用和惯用,我会采用以下方式:

(apply concat
  (for [x [1 2 3 4]
        :let [name (str "check" x)]]
    [(check-box name)
     (label name (capitalize name))]))

for通过将变量(或多个变量)(在本例中为x)绑定到一个序列的一个元素并循环直到它经历了所有这些元素来工作。通过这种方式,它会经过1,2,3和4,然后在let绑定名称中(str "check" x)。例如,在第一次迭代中,name将绑定为“check1”。其余的只是使用适当的参数调用check-boxlabel函数。

如果你想进一步概括这一点 - 例如,你可能不知道你想要多少个复选框和标签 - 你可以这样轻松地做到这一点:

(defn make-n-checkboxes-and-labels
  [n]
  (apply concat
    (for [x (range 1 (inc n))
          :let [name (str "check" x)]]
      [(check-box name)
       (label name (capitalize name))])))

在这种情况下,它现在被推广到一个函数,你可以做与以前完全相同的事情,但现在通过这样做:

(make-n-checkboxes-and-labels 4)

同样,我没有对打嗝做任何研究,所以我可能不知道你想要做什么。此外,蒂莫西可能会建议(隐式地,不明确地),用关键字替换你的字符串。我会重申这个建议,因为关键字应该更快更好看(在这种情况下,它们也可能更惯用)。如果你想用关键字替换你的字符串,那么将(keyword)包裹在字符串周围应该是一件简单的事情,如下所示:

(keyword (str "check" 1))
=> :check1
祝你好运!