使 Clojure let 语句更具功能性
Making Clojure let statement more 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))))
缩进看起来不对,感觉不实用,因为我在 let 块中重用状态。我基本上先数一下损坏的标牌数量,然后再数可修复标牌的数量。如果任何标志是不可修复的,我打印-1,否则我打印要修复的标志数。
如果我 mapped/filtered 两次,我会有重复的代码,但最重要的是它会 运行 变慢。尽管如此,是否有改进此代码的方法?
编辑:这是我确定的
(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))
减法确实没有必要,计数也不必发生在 let 块中。在输入错误时输出 -1 也不是函数的工作,只是任务的一部分。
您的代码没有副作用(打印除外,我们会修复),所以我不会说它不起作用。 let
专为建立中间值而设计。在评论中有一些潜在的改进。
; align here (controversial)
(let [broken-signs (->> (:symbols field)
(map make-sign)
(filter broken?))
broken-count (count broken-signs)
unfixable-count (->> broken-signs ; maybe emphasize non-function start
(filter (complement fixable?))
count)] ; no parens needed
;; don't print; just return number
(if (< 0 unfixable-count) ; prefer less-than (Elements of Clojure book)
-1
(- broken-count unfixable-count)))
我强烈推荐 Clojure Style Guide 以获得相关建议。
我认为您的方法没有任何 "non-functional" 或错误。缩进看起来不错。
(let [broken (->> (:symbols field)
(map make-sign)
(filter broken?))
unfixable (remove fixable? broken)]
(when (seq unfixable)
(- (count broken) (count unfixable))))
- 您可以将
filter (complement
替换为 remove
- 可以使用
pos?
而不是 (> n 0)
- 我可能会在
if
中放两个 println
,但实际上最好 return 一个值
- 您可以内联
broken-count
绑定,因为它只用在一个地方
- 我个人认为使用较少的线程宏更容易阅读
- 由于需要计算
unfixable
s 是有条件的,您可以先用 seq
测试值
- 如果你 return
-1
作为标记值,我会用 nil
代替;当不满足 when
条件时,这自然会发生
- 条件逻辑似乎倒退:当
unfixable-count
为正时你return-1
,只有当它不是正时才使用它的值(这意味着它是零b/c计数不能为负数),例如它可以重写为 (- broken-count 0)
然后只是 broken-count
(let [broken-signs (->> (:symbols field)
(map make-sign)
(filter broken?))]
(if-let [unfixable-signs (seq (remove fixable? broken-signs))]
-1
(- (count broken-signs) (count unfixable-signs)))
您的代码已经非常简洁且布局合理。我想做的唯一改变是尽可能长时间地留在域中——在本例中是 signs
对象。并且只在很久以后使用计数。
return 值然后可以使用打印来执行实际操作。
在我的第一个 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))))
缩进看起来不对,感觉不实用,因为我在 let 块中重用状态。我基本上先数一下损坏的标牌数量,然后再数可修复标牌的数量。如果任何标志是不可修复的,我打印-1,否则我打印要修复的标志数。
如果我 mapped/filtered 两次,我会有重复的代码,但最重要的是它会 运行 变慢。尽管如此,是否有改进此代码的方法?
编辑:这是我确定的
(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))
减法确实没有必要,计数也不必发生在 let 块中。在输入错误时输出 -1 也不是函数的工作,只是任务的一部分。
您的代码没有副作用(打印除外,我们会修复),所以我不会说它不起作用。 let
专为建立中间值而设计。在评论中有一些潜在的改进。
; align here (controversial)
(let [broken-signs (->> (:symbols field)
(map make-sign)
(filter broken?))
broken-count (count broken-signs)
unfixable-count (->> broken-signs ; maybe emphasize non-function start
(filter (complement fixable?))
count)] ; no parens needed
;; don't print; just return number
(if (< 0 unfixable-count) ; prefer less-than (Elements of Clojure book)
-1
(- broken-count unfixable-count)))
我强烈推荐 Clojure Style Guide 以获得相关建议。
我认为您的方法没有任何 "non-functional" 或错误。缩进看起来不错。
(let [broken (->> (:symbols field)
(map make-sign)
(filter broken?))
unfixable (remove fixable? broken)]
(when (seq unfixable)
(- (count broken) (count unfixable))))
- 您可以将
filter (complement
替换为remove
- 可以使用
pos?
而不是(> n 0)
- 我可能会在
if
中放两个println
,但实际上最好 return 一个值 - 您可以内联
broken-count
绑定,因为它只用在一个地方 - 我个人认为使用较少的线程宏更容易阅读
- 由于需要计算
unfixable
s 是有条件的,您可以先用seq
测试值 - 如果你 return
-1
作为标记值,我会用nil
代替;当不满足when
条件时,这自然会发生 - 条件逻辑似乎倒退:当
unfixable-count
为正时你return-1
,只有当它不是正时才使用它的值(这意味着它是零b/c计数不能为负数),例如它可以重写为(- broken-count 0)
然后只是broken-count
(let [broken-signs (->> (:symbols field)
(map make-sign)
(filter broken?))]
(if-let [unfixable-signs (seq (remove fixable? broken-signs))]
-1
(- (count broken-signs) (count unfixable-signs)))
您的代码已经非常简洁且布局合理。我想做的唯一改变是尽可能长时间地留在域中——在本例中是 signs
对象。并且只在很久以后使用计数。
return 值然后可以使用打印来执行实际操作。