如何在if-let中嵌套let来编写一次函数调用?

时间:2013-07-10 19:00:08

标签: clojure

我有这些功能:

(def i (atom {})) ;incremented/calculated file stats

(defn updatei [n fic fos]
  (swap! i conj {(keyword n)[fic fos]}))

(defn calcfo [fo fi fis]
  (if-let [n (get @i fo)] ;find a previous record?
    (let [fic (inc (first n)), fos (+ fis (second n))] ;increment the stats
      (updatei fo fic fos))
    (let [fic 1, fos fis] ;if not then: first calc recorded
      (updatei fo fic fos))))

我怎么能写(updatei fo fic fos)一次,而不是在函数中列出两次?有秘密还是让我不知道?

- 假设代码 -

(defn calcfo [fo fi fis]
  (if-let [n (get @i fo)] ;find a previous record?
    (let [fic (inc (first n)), fos (+ fis (second n))] ;increment the stats
    (or-let [fic 1, fos fis] ;if not then: first calc recorded
      (updatei fo fic fos)))))

或者我是否在功能上强调这一点?

编辑:

我觉得这对我来说最有意义:

(defn calcfo [fo fis]
  (apply updatei fo
  (if-let [[rfc rfos] (get @i fo)] ;find a previous record?
       [(inc rfc) (+ rfos fis)] ;increment the stats
       [1 fis]) ;if not then: first calc recorded
      ))

感谢您的答案!

3 个答案:

答案 0 :(得分:3)

如何使用if然后进行解构?这是一种方法:

(defn calcfo [fo fi fis]
  (let [n         (get @i fo)                                 ;find a previous record?
        [fic fos] (if n 
                    [(-> n first inc) (-> n second (+ fis))]  ;increment the stats
                    [1 fis])]                                 ;if not then: first calc recorded
      (updatei fo fic fos)))

参数fi似乎没有被使用,所以也许你可以从参数列表中删除它。

(defn calcfo [fo fis] ,,,)

使用first格式绑定second时使用解构也可以避免使用nlet

(defn calcfo [fo fis]
  (let [[x y & _]  (get @i fo)
        [fic fos]  (if x [(inc x) (+ fis y)] [1 fis])]
    (updatei fo fic fos)))

答案 1 :(得分:3)

重新排列可能会有所帮助

(defn calcfo [fo fi fis]
  (apply updatei fo
    (if-let [n (get @i fo)]
      [(inc (first n)), (+ fis (second n))]
      [1, fis] )))

答案 2 :(得分:2)

我认为如果你重新编写updatei,你会回避整个问题并使你的代码更好,例如:

 (defn- safe+ [a b]
   (if a (if b (+ a b) a) b))
 (defn updatei [n fic fos]
   (swap! i update-in [(keyword n)] #(vector (safe+ fic (first %)) (safe+ fos (second %)))))

可能有更好的方法来编写该代码,但基本的想法是使用update-in来存储新值(如果之前没有为该键存储任何内容),或者将它们与已经存在的内容相结合那里。