使Clojure让语句更具功能性

Pos*_*elf 2 functional-programming clojure purely-functional

在我的第一个Clojure项目中,除了最后这部分外,一切都很顺利:

(let [broken-signs    (->> (:symbols field)
                           (map make-sign)
                           (filter broken?))
      broken-count    (count broken-signs)
      unfixable-count (-> (filter (complement fixable?) broken-signs)
                          (count))]
  (println
    (if (> unfixable-count 0)
      -1
      (- broken-count unfixable-count))))
Run Code Online (Sandbox Code Playgroud)

缩进看起来很不正常,因为我在let块中重用了state.我基本上计算了破损标志的数量,然后计算了可固定标志的数量.如果任何标志是不可修复的,我打印-1,否则我打印要修复的标志数量.

如果我映射/过滤两次,我会有重复的代码,但最重要的是它运行速度较慢.有没有办法改进这个代码呢?

编辑:这是我坚持的

 (defn count-broken-yet-fixable []
   (let [broken (->> (:symbols field)
                     (map make-sign)
                     (filter broken?))
         unfixable (remove fixable? broken)]
     (when (empty? unfixable)
       (count broken))))

 (defn solve-task []
   (if-let [result (count-broken-yet-fixable)]
     result
     -1))

(println (solve-task))
Run Code Online (Sandbox Code Playgroud)

减法确实没有必要,并且计数不必发生在let块中.在错误输入上输出-1也不是函数的工作,而只是任务的一部分.

Tay*_*ood 9

我不认为你的方法有任何"非功能性"或错误.缩进看起来很好.

(let [broken (->> (:symbols field)
                  (map make-sign)
                  (filter broken?))
      unfixable (remove fixable? broken)]
  (when (seq unfixable)
    (- (count broken) (count unfixable))))
Run Code Online (Sandbox Code Playgroud)
  • 你可以替换filter (complement使用remove
  • 可以用pos?而不是(> n 0)
  • 我可能会把两个printlns放进去if,但最好还是返回一个值
  • 你可以内联broken-count绑定,因为它只在一个地方使用
  • 我个人认为使用较少的线程宏更容易阅读
  • 由于需要计算unfixables是有条件的,你可以测试与价值seq第一
  • 如果你-1作为哨兵价值返回,我会nil改用; 当when条件不满足时,这自然会发生
  • 条件逻辑似乎是倒退的:-1当你unfixable-count是正数时你返回,只有当它不是正数时才使用它的值(这意味着它的零b/c计数不能为负),例如它可以被重写为(- broken-count 0)然后只是broken-count