我学会了与Clojure更加惯用。我觉得我的以下实现可能更惯用,更简单:
(defn refine-previous-week-and-year [initial-year, initial-week]
;; Returns the week number and year of previous week,
;; taking consideration if the current week is 1st week of a year,
;; then the previous week is the week 52 of the last year.
;; If the initial week number is not nil, keep it as the week number.
;; If the initial year number is not nil, keep it as the year number.
;; If the intial year is nil, return the current year, unless, the initial-week is nil,
;; and the previous week is the week 52 of the last year, then return last year.
;; If the inital week number is nil, then the previous week number is current week minus one,
;; unless, the current week 1, then the previous week is 52, and the year is last year.
(cond
(and initial-week initial-week) [initial-year initial-week]
(nil? initial-week) (let [previous-week-raw (- (current-week) 1)]
(if (= 0 previous-week-raw)
[(if initial-year initial-year (- (current-year) 1)) 52]
[(if initial-year initial-year (current-year)) previous-week-raw]))
(nil? initial-year) [(current-year) initial-week]))
考虑输入参数是否为零,存在复杂的逻辑,考虑前一周的逻辑是去年。
非常感谢你的帮助!
于
修改
基于评论和建议,这是我的改进版本:
(defn refined-previous-week-and-year
"
Returns the week number and year of previous week,
taking consideration if the previous week is the last week
(52) of the last year.
If the raw-week number is not nil, keep it as the week number.
If the raw-year number is not nil, keep it as the year number.
If the raw-year is nil, return the current year,
unless the raw-week is nil, and the previous week is the last week (52)
of the last year, then return last year.
If the raw-week number is nil,
then the previous week number is current week minus one,
unless the previous week is the last week (52) of the last year,
and the year should be last year.
"
[raw-year, raw-week]
(let [real-year-and-previous-week (memoize (fn [] (let [previous-week-computed (dec (current-week))
year (current-year)]
(if (= 0 previous-week-computed)
{:year (dec year) :week 52}
{:year year :week previous-week-computed}))))
real-year (fn [] (:year (real-year-and-previous-week)))
real-previous-week (fn [] (:week (real-year-and-previous-week)))]
{:year (or raw-year (real-year)) :week (or raw-week (real-previous-week))}))
我使用函数和memoize来计算实际和实际上一周的懒惰。我想知道是否可以通过更简单的方法实现它?
使用(或x y)表达式,逻辑更简单,我已经解决了处理原始参数为零的卷积,以及使用函数捕获计算的前一周的计算。
非常感谢您帮助我学习!
答案 0 :(得分:2)
以下是一些您可以申请更加惯用的规则:
您的代码似乎并不像所有情况所宣传的那样工作,并且可以更简单,主要是通过将两个输入值视为需要默认的东西(如果它们不存在)。在那之后,过程始终是相同的
(defn refine-previous-week-and-year
"Returns the week number and year of previous week,
taking consideration if the current week is 1st week of a year,
then the previous week is the week 52 of the last year."
[input-year input-week]
(let [year (or input-year (current-year)) ; Use current year/week
week (or input-week (current-week))] ; if none provided
(if (= 1 week)
[(dec year) 52]
[year (dec week)])))
编辑:
我似乎并不了解您的要求,但我认为您的评论具有误导性,因此我删除了文档字符串。为了得到我认为你想要的行为,我将其分成两个更简单的函数:
(defn previous-week
[year week]
(if (= 1 week)
[(dec year) 52]
[year (dec week)]))
(defn previous-week-if-no-week
[input-year input-week]
(let [year (or input-year (current-year))]
(if input-week
[year input-week]
(previous-week year (current-week)))))