请在2024 Clojure调查问卷中分享您的想法![a style="color:#34495e;" href="https://www.surveymonkey.com/r/clojure2024"]

欢迎!有关此页面如何工作的更多信息,请参阅关于页面。

0
Clojure

Rich今天在IRC提到,他欢迎 clojure.core/range 的减少器实现。既然我已经弄清楚了如何进行迭代,我想在今晚结束前完成range。现在就提前公开这个问题,通知任何对此感兴趣的人。

24个答案

0

评论者为:amalloy

实现了range。附带了单独的提交,使iterate和range也具有Seqable,因为我不确定这是否需要。按需应用或放弃。

0

评论者为:jasonjckn

range应该是可折叠的

0

评论者为:amalloy

是的,应该是这样的。现在是时候深入研究折叠实现了!

0

评论者为:amalloy

我应该将这些提交合并为一个吗?我不知道在JIRA上更受欢迎,也不知道range/iterate是否应该是seqable,或者我应该只放弃第二个提交。

0

评论者:richhickey

是的,请将它们合并在一起,否则很难看清(我几乎看不清楚差异 :)。range 和 iterate 在 reducers 中不应该有什么新的,而应该是增强核心函数的返回值。增强(例如协议扩展)可以通过要求使用 reducers 来实现,因为没有它无法利用。而且,我不确定对于 'splittable' 的分配协议我有什么感觉——到目前为止我一直避免使用它。

0

评论者为:amalloy

所以你想让 clojure.core/range 返回某种对象(一个 Range),该对象实现 Counted 和 Seqable(但不仅仅是 lazy-seq),然后在 clojure.core.reducers 中将 CollReduce 和 CollFold 扩展到该类型?好的,我可以做到。

我不太明白您所说的分配协议是什么意思。我明白您的观点,我的 fold-by-halves(它接受一个函数作为输入)与具有单个函数的协议类似,但它并不比 foldvec 已经做的多分配任何东西——我只是将这个逻辑提取出来,这样就不需要在每个可折叠的类型中重复 fork/join 的繁琐工作。您有其他的建议吗,还是这只是让您觉得不安,您仍在考虑中?

0

评论者:richhickey

虽然 vector-fold 分配子向量,但 halving-fn 必须对所有实现返回一个新向量。没问题,我认为这不太可能成为主导因素(因为 fj 仍然需要新的闭包)。请继续,但请将 range 和 iterate 保存在 core 中。它们是源,不是转换器,而只有转换器(那些必须与基于 seq 的对应物不同)必须位于 reducers 中。谢谢!

0

评论者:stuart.sierra

最好有一个大的补丁文件,虽然该文件可能包含多个提交,如果这使得意图更清楚的话。

添加补丁时,请更新问题的描述,表明哪个文件是最新的。保留旧补丁文件以供历史参考。

0

评论者为:amalloy

将迭代和范围移动到 core.clj 中比我想的要困难得多。我的计划是只让它们实现 Seqable 接口,这虽然不难,但它们现在实际上是 ISeq 的实例,因为它们继承了 LazySeq。许多代码都依赖于它们是 ISeq 的实例(例如,在 repl 中打印它们),所以我不能简单地忽略它们。实现所有这些方法(大约三十个)需要大量的代码,而这些代码很难在 Iteration、Range 以及 future reducible sources 中共享。

我可以编写一个宏,如 (defseq Range (link: start end step) Counted (count (link: this) ...) ...),它接受正常的 deftype 参数,并在较高层面添加 ISeq、Collection 等实现的代码,其中 (.seq this) 将是一个 LazySeq。然而,这看起来像是有点尴尬的方法,我会有点不好意思把它放在 core.clj 中。如果有人有更好的方案,我会很乐意听取。在另一方面,我将继续进行这个宏实现,以防它最终是最好的选择。

0

评论者为:amalloy

-- 此补丁包含至 CLJ-992 的所有以前补丁 --

为了创建一个既是延迟序列又是
可收紧源的的对象,我需要在 core_deftype 中添加一个名为 defseq 的宏。
它基本上是将 clojure.lang.LazySeq 作为 clojure 宏的重新实现,以便我可以将延迟序列函数混合到任何方法的新类中,这些方法对于缩减和折叠是必需的。
如果我们愿意,我们可以使用这个宏在 clojure 中而不是在 java 中实现 lazy-seq,但这与此补丁无关,因此我没有这样做。
如前所述,defseq 可能不是一个正确的方法,但这个方法有效,直到有人提出更好的方案为止。

如前述评论中所提到的,defseq 可能不是一个正确的方法,但这在此阶段仍然有效,直到有人提出更好的方案。

0

评论者为:amalloy

我在这个补丁中意外地包含了一个 drop-while 的实现,我对它进行了一些测试以确保我理解这一切是如何工作的。我认为我会暂时保留它,因为它有效且有用,但如果现在不想使用它,我可以删除它或将它移动到一个新的 JIRA 问题中。

0

评论者:richhickey

好的,我认为这个补丁已经偏离了轨道。必须有一种更好的方法。让我们先从以下几点开始:触摸core/deftype并重新实现lazy-seq作为宏,这些方法都被排除在外。range函数的返回值不必必须是LazySeq,它必须是延迟序列,例如,实现ISeq(7个方法,而不是30个),它可以通过将其现有实现分配出去来实现。它还可以实现一些新接口供reducer逻辑使用。clojure.lang.Range仍然存在,这是另一种方法。在这些事情上请采取极其保守的方法。

0

评论者为:amalloy

好的,感谢您的反馈——我很高兴我在之前的补丁中进行时知道这可能是错误的:)。我认为我需要实现LazySeq实现的Java集合接口,例如java.util.List,以避免破坏像(defn range-list (链接:n) (ArrayList. (range n)))这样的互操作函数。如果只需要实现ISeq(从而实现IPersistentCollection),那么这相对容易管理。

尽管如此,对于每个新来源来说,它仍然是一个不愉快的样板代码块;如果我不将其放入core_deftype中,您会接受一个像defseq这样的宏吗?如果是这样,似乎最好实现互操作接口;如果不是,我可以跳过它们,并为每种新的源类型实现ISeq、IPersistentCollection和Seqable中的7个(难道不是9个?)方法。

感谢您指出clojure.lang.Range给我——我没有意识到我们那里有这个。当然,通过实现继承,它很容易让Range、Iteration等继承自LazySeq,并从它们扩展协议。但这意味着将功能从clojure移到java,我觉得我们不太想这么做。

我将为这两种新的类型手动实现ISeq,并将在今天稍后附带补丁。

0

评论者为:amalloy

我已经编写了一个实现ISeq的补丁,但没有实现java Collections接口,它大致可以工作,但在clojure.core和clojure.lang的一些部分中有明确假设序列是集合。对我来说最明显的是(即,当运行mvn测试时它会显示),RT/toArray测试为Collection,但从未测试为ISeq,这意味着它不愿意处理不是集合的ISeq。依赖于toArray的函数(例如to-array和vec)现在失败了。

这个补丁包含了之前关于该问题的所有补丁,但不适合应用程序,因为它留下了一些失败的测试——它仅用于中间反馈。

0

评论者:richhickey

如果时间允许,您能否在开发维基上总结一下您所发现的问题、挑战和选项(即使只是一个简单的表格也很好)。我明白这是一项具有挑战性的任务,或许在这个阶段,我们应该选择更为谦逊的reducers/range和reducers/iterate,使两个世界保持独立。我希望能有一天统一range功能,因为我们有很多人现有的range亟待能够折叠,就像现有的向量一样。

欢迎来到Clojure问答社区,在这里您可以提出问题并从Clojure社区成员那里获得答案。
...