分享您的想法,请参与 2024 年 Clojure 状况调查!

欢迎!请参阅 关于 页面以了解更关于如何进行的信息。

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应该是可迭代的还是我应该只丢弃第二个提交。

0

评论由:richhickey发表

是的,请将它们合并在一起,否则很难看清楚(我自己都几乎看不清差异 :)。range和iterate不应该在reducers中是创新的,而应该是增强核心函数的返回值。增强(例如协议扩展)可以通过要求reducers来实现——因为这不能在没有它的支持下使用。此外,我不太确定我对于'可分割的'的分配协议的看法——迄今为止我一直在避免它。

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在核心中。它们是数据源,而不是转换器,只有转换器(与基于seq的对应物必须不同)必须存在于reducers中。谢谢!

0

评论由:stuart.sierra发表

一个大的补丁文件是首选,尽管该文件可能包含多个提交,如果这将使意图更加清晰。

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

0

评论由:amalloy 提出

将迭代和范围移动到core.clj内核似乎比预期的要难。我的计划是让它们只实现Seqable,这很简单,但当前它们实际上是ISeq的实例,因为它们继承自LazySeq。大量的代码(例如,在repl中打印它们)都依赖于它们是ISeq,所以我不能简单地忽略它。实现这些所有方法(大约有三十个)需要大量的代码,这些代码在Iteration、Range和添加到core.clj内核的任何未来的可还原源之间难以共享。

我可以写一个宏,如(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中实现lazy-seq,而不是在java中实现,但这与此补丁无关,所以我没有这样做。

如前所述,defseq可能不是正确的做法,但这是在更好的方法提出之前的工作。

0

评论由:amalloy 提出

我在这个补丁中意外地包含了一个关于drop-while的实现,我尝试用这个实现来确保我理解了这一切是如何工作的。我想我会暂时保留它,因为它是有效的并且有用,但如果现在不需要,我可以移除它,或者将其移动到一个新的JIRA任务中。

0
答者

评论由:richhickey发表

好了,我认为这个补丁已经偏离了正确的轨道。必须有一个更好的方法。让我们从:涉及 core/deftype 和重新实现 lazy-seq 作为宏的方案被排除在外开始。range 的返回值不一定要 LazySeq,它只需要是一个 lazy seq,例如,实现 ISeq(7 个方法,而不是 30 个),它可以通过委派给现有的实现来实现。它还可以实现一个用于减法逻辑的新接口。clojure.lang.Range 仍然存在,这也是另一个方案。在这些事情上请采取极其谨慎的方法。

0
答者

评论由:amalloy 提出

好吧,感谢你的反馈——我很高兴我在进行最后一个补丁时知道它可能是不正确的 :)。我曾以为我需要实现 LazySeq 实现的 Java 集合接口,例如 java.util.List,以避免破坏像 (defn range-list (link: n) (ArrayList. (range n))) 这样的互操作函数。如果只实现 ISeq(以及因此 IPersistentCollection)就足够了,那么这还是相当容易管理的。

尽管如此,对于每个新的源代码来说,这仍然是一大堆不便的模板代码;如果我将 defseq 放到 core_deftype 中,你会欢迎它吗?如果是这样,那么似乎最好实现互操作接口;如果不是,我可以跳过它们,并为每个新的源类型实现 ISeq,IPersistentCollection 和 Seqable 的 7 个(难道不是更多?)方法。

感谢你指出 clojure.lang.Range —— 我没有意识到我们这里有它。当然,通过实现继承,使 Range,Iteration 等继承自 LazySeq 并从它们扩展协议很容易。但这意味着将功能从 clojure 移动到 java,而这并不是我们想要做的。

我会准备一个补丁,其中手写实现这两个新类型等的 ISeq,很可能在今天稍晚些时候完成。

0
答者

评论由:amalloy 提出

因此,我已经编写了一个实现 ISeq 但不实现 java Collections 接口的补丁,它基本工作,但 clojure.core 和 clojure.lang 的某些部分在运行 mvn test 时确实存在一些假设是因为 seqs 是集合。对我来说最明显的是(也就是说,它在运行 mvn test 时会出现):RT/toArray - 它测试 Collection,但从不在 ISeq 上测试,这意味着它不愿意处理不是集合的 ISeq。依赖于 toArray(例如 to-array 和 vec)的函数现在失败。

这个补丁包括了此问题上所有的前一个补丁,但不适用于应用程序,因为它留下了一些失败的测试——它只适用于中间反馈。

0
答者

评论由:richhickey发表

如果时间允许,您能够在开发者维基上记录下您发现的这些问题、挑战和选项,那将会非常有助于我们(哪怕是简单的表格也会非常棒)。我明白这已经是一个很有挑战性的任务,也许在这个时候,我们应该选择更为谦虚的reducers/range和reducers/iterate,让这两个领域各自独立。我最终希望将range进行统一,因为现在有很多现存的range,如果能像现有的向量一样进行折叠,那将会非常棒。

欢迎使用Clojure问答社区,在这里你可以向Clojure社区的成员提问并获得答案。
...