请在 2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请查看 关于 页面,了解更多关于这个网站如何运作的信息。

0
Clojure

Rich 今天在 IRC 上提到,他欢迎 clojure.core/range 的分组器实现。既然我已弄清楚如何进行迭代,我想今晚就把 range 完成吧。现在我先提前打开这个 issues,告诉感兴趣的其他人我的意图。

24 答案

0

评论者:amalloy

实现了 range。我还附上了一个单独的提交,使 iterate 和 range 也成为 Seqable,因为我不知道这是否是被期望的。根据您的喜好应用或不应用。

0

评论者:jasonjckn

range 应该是可折叠的

0

评论者:amalloy

是的,所以它应该是这样的。现在是时候深入挖掘折叠实现了!

0

评论者:amalloy

我应该把这些所有提交合并成一个吗?我不知道 JIRA 上更倾向于哪种做法,我也不清楚 range/iterate 是否应该是 seqable 的,还是我应该只丢弃第二个提交。

0

评论人:richhickey

是的,请将这些合并在一起,否则难以看清(我读起来几乎难以区分差分:)。range 和 iterate 不应该在 reducers 中是新颖的,而只应该是核心函数增强的返回值。增强(例如协议扩展)可以通过要求 reducers 来实现,因为这不能在没有它的情况下利用。此外,我对“可分裂”的分配协议的感受还不确定——迄今为止我一直在避免使用它。

0

评论者:amalloy

所以你希望 clojure.core/range 返回一个对象(一个范围),该对象实现 Counted 和 Seqable(但不仅仅是一个懒序列),然后在 clojure.core.reducers 中扩展 CollReduce 和 CollFold 到该类型?好的,我能做到。

我不太明白你所说的分配协议是什么意思。我懂你的意思,我的 fold-by-halves 函数(它接受一个函数)与只有一个函数的协议类似,但它不会比 foldvec 已经做的更多分配——我只是把那个逻辑提出来,这样在所有可折叠的内容中就不需要重复分叉/连接的工作。你有其他的建议,还是只是让你感到不安,你还在考虑?

0

评论人:richhickey

尽管 vector-fold 会分配子向量,但 halving-fn 必须对所有实现返回一个新的向量。没问题,我认为这不会占主导地位(因为 fj 需要新的闭包)。请继续,但请将 range 和 iterate 保持核心。它们是源,不是转换器,只有转换器(它们必须与基于 seq 的对应物不同)必须位于 reducers 中。谢谢!

0

评论人:stuart.sierra

最好是一个大补丁文件,虽然这个文件可能包含多个提交,如果这能更清楚地表达意图的话。

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

0

评论者:amalloy

将迭代器和范围移动到 core.clj 的工作比预期的要困难。我的计划是只让它们实现 Seqable,这虽然很容易,但它们实际上是 ISeq 的实例,因为它们继承自 LazySeq。许多代码片段(例如,在 repl 中打印它们)都依赖于它们是 ISeq,所以我不能简单地忽略它们。实现所有这些方法(大约三十个)需要大量的代码,而这些代码很难在迭代器、范围以及未来添加到 core.clj 中的任何可缩减源之间共享。

我可以编写一个宏,例如 (defseq Range (link: start end step) Counted (count (link: this) ...) ...),它接受正常的 deftype 参数,并添加对 ISeq、Collection 等的 ISeq、Collection 等实现,这些实现将基于 (.seq this),这是一个 LazySeq。然而,这似乎是一种有点尴尬的方法,我会有点尴尬地向 core.clj 中添加。如果任何人有更好的替代方案,我会很高兴听到它。与此同时,我将继续进行这个宏的实现,以防它最终成为最佳选择。

0

评论者:amalloy

此补丁涵盖了之前针对此问题和 CLJ-992 的所有补丁。

为了创建一个既是惰性序列又是可缩减源的
对象,我需要在 core_deftype 中添加一个名为 defseq 的宏。
它基本上是 clojure.lang.LazySeq 的宏重实现,这样我就可以
将懒惰序列函数“混合”到任何需要用于减少和折叠的成功
的新类。

如果我们愿意,可以使用这个宏在 clojure 中实现 lazy-seq,而不是在 Java 中实现,但这与此补丁无关,所以我没有这样做。

如前所述,defseq 可能不是正确的方法,但这是在提出更好的方法之前的一个解决方案。

0

评论者:amalloy

我无意中把这个补丁中包含了一个 drop-while 的实现,我在尝试确保我明白这一切是如何工作的。我想我会让它安静地留在那里,因为它是有效的并且很有用,但如果现在不需要,我可以把它移除,或者把它转移到新的 JIRA 任务。

0

评论人:richhickey

好的,我认为这个补丁已经完全偏离了轨道。一定有更好的办法。让我们从放弃修改 core/deftype 和以宏的形式重新实现 lazy-seq 开始。范围的返回值不必是 LazySeq,它必须是惰性序列,即通过实现 ISeq(7 个方法,不是 30 个)来实现,这可以通过将其现有的实现转包来实现。它还可以实现一些新接口,供缩减逻辑使用。那里仍然有 clojure.lang.Range,这是另一种方法。在这些事情上请采取极为保守的方法。

0
已回答 通过

评论者:amalloy

好了,谢谢你的反馈——我很高兴我知道那个最后的补丁可能不正确。我以为我需要实现LazySeq的Java集合接口,比如java.util.List,以避免破坏诸如(range n)(ArrayList.)之类的互通函数。如果只需要实现ISeq(以及IPersistentCollection),那么这相当容易管理。

尽管如此,对于每个新的源来说,这仍然是一大堆样板代码;如果你不把defseq宏放在core_deftype中,你会接受这样的宏吗?如果是这样,那么或许最好实现互通接口;如果不是,我可以跳过它们,并为每个新源类型实现ISeq、IPersistentCollection和Seqable中的7(不是9个)方法。

感谢你向我指出clojure.lang.Range——我没有意识到我们在那里有它的作用。当然,有了实现继承,它会很容易让Range、Iteration等从LazySeq继承,并从它们扩展协议。但这意味着将功能从clojure移到java,而我们本来可能不想这么做。

我今天晚些时候将手动为这两种新的类型分别实现ISeq,并将其包含在一个补丁中。

0
已回答 通过

评论者:amalloy

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

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

0
已回答 通过

评论人:richhickey

如果你有时间,请在dev wiki中记录你发现的问题、挑战和选项会有很大帮助(即使是简单的表格都会很棒)。我明白了这已经是一项挑战性的任务,此时我们可能应该选择更适度的reducers/range和reducers/iterate,让两者分开。我最终希望统一range,因为有许多现存的range,如果能像现存的vector一样折叠它们,那就很好了。

欢迎来到Clojure Q&A,在这里您可以向Clojure社区的成员提问并获取答案。
...