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 结束值)
(thru 开始值 结束值)
(thru 开始值 结束值 步长)

返回一个数字序列。类似于 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)
原始问题已经特别讨论了这种情况

不幸的是,这并不等同于将结束参数添加到 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)`在原始问题中很明显不包含`end`。所以如果可以精确指定函数的期望行为,通过转换参数并将其传递给`range`,就可以简单地实现它。正如Eugene Pakhomov提到的,这可能涉及到将步长值加到`end`上,然后再使用`floor`函数得到要传递给`range`的`end`值。
...