请分享您的看法,参加2024 年 Clojure 状态调查!

欢迎!请访问关于页面了解更多功能信息。

0
序列

范围不包含结束参数。例如

> (range 1 3)
(1 2)

我想有一个像范围一样,但包含端点的函数

> (inclusive-range 1 3)
(1 2 3)

遗憾的是,这并不等同于将结束值添加到范围返回的序列中。例如

> (inclusive-range 1 2.5)
(1 2)

我相信 Clojure 中没有直接提供这项功能,但我发现这很有用。我编写了一个可以工作的函数(但不是惰性的)。

(defn inclusive-range
  "Return a sequence of nums from START to END, both inclusive, by STEP."
  ([start end]
   (inclusive-range start end 1))
  ([start end step]
   (let [test-for-done (if (< start end)
                         >
                         <)]
     (if (test-for-done start (+ start step))
       []
       (loop [nums []
              cur start]
         (if (test-for-done cur end)
           nums
           (recur (conj nums cur)
                  (+ cur step))))))))

我是否遗漏了更好的做法?这能否添加到 Clojure 中?

2 个回答

+1

我经常需要类似的功能,所以我写了这个 thru 函数

`
tupelo.core/thru

(thru end)
(thru start end)
(thru start end step)

返回一个数字序列。类似于 clojure.core/rng,但包含右边界值。不是惰性的。
`

0

有一点想法,尽管我不完全确定我完全理解了你的要求/想法

> (defn inclusive-end-range 
    [start end]
    (range start (inc end)))
#'inclusive-end-range
> (inclusive-end-range 1 3)
(1 2 3)
OP特别涵盖了那个情况

遗憾的是,这并不等同于将结束值添加到范围返回的序列中。例如

> (inclusive-range 1 2.5)
(1 2)

(range 1 (inc 2.5)) => (1 2 3)而不是。
这似乎会被floor涵盖,所以 `#(range %1 (inc (Math/floor %2)))`。当添加步长参数时,它会更复杂,但也是可行的,并且比原始的基于循环的解决方案简单。
Sean,你说得对 - 我误读了那部分。感谢你澄清,并为之前的噪音道歉。
原本我要写一个答案,但后来意识到我做不到,因为这个问题表述不当,这次讨论也显示了原因。当开始使用分数值表示“结束”时,讨论“包括结束”就变得没有意义。例如 `(inclusive-range 1 2.5)` 明显不包括结束,即使在原始问题中也是如此。所以如果可以精确地指定函数的期望行为,就可以通过转换参数然后将它们传递给 `range` 来简洁地实现它。正如Eugene Pakhomov提到的,这可能涉及将步长值加到 `end` 上,并使用 `floor` 得到要传递给 `range` 的 `end` 值。
...