2024 年 Clojure 状况调查! 中分享你的想法。

欢迎!请查看 关于 页面以获取更多关于该网站如何运作的信息。

0
序列

Range 不包含结束参数。例如

> (range 1 3)
(1 2)

我想得到一个类似于 range 的函数,但是包含结束状态

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

不幸的是,这并不等同于给 range 返回的 seq 中添加结束参数。例如

> (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专门讨论了那个案例

不幸的是,这并不等同于给 range 返回的 seq 中添加结束参数。例如

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

(range 1 (inc 2.5)) => (1 2 3)。
这似乎可以通过 `floor` 解决,所以 `#(range %1 (inc (Math/floor %2)))`。当添加步长参数时,这会更复杂,但仍然是可实现的,并且比原始的 `loop` 基解决方案更简单。
Sean,你是对的 - 我误解了这一点。感谢澄清,抱歉造成混乱。
本想写一个答案,但后来意识到我无法这么做,因为问题表述不明确,这个讨论展示了原因。当你开始对`end`使用分数值时,谈论“包括末尾”就变得没有意义了。例如 `(inclusive-range 1 2.5)` 明显不包括末尾,即使是在原始问题中也是如此。所以,如果可以精确地指定函数的期望行为,通过转换参数并将它们传递给 `range`,就可以简单地实现它。正如 Eugene Pakhomov 所提到的,它可能涉及到将步长值加到 `end` 上,然后使用 `floor` 函数对结果进行取整,以得到传递给 `range` 的 `end` 值。
...