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

欢迎!请阅读 关于页面 了解更多关于这个网站的信息。

0
Clojure

Rich 在今天的IRC中提到,他欢迎 clojure.core/range 的 reducer 实现。既然我已经明白了如何进行迭代,我想在今晚结束时也会对 range 进行同样的处理。现在提前开放这个议题,以通知任何对此感兴趣的人。

24 答案

0

评论者:amalloy

实现了 range。附带了单独的提交,使 iterate 和 range 也成为 Seqable,因为我不确定这是否是所需的。按需应用或不应用,随意。

0

评论者:jasonjckn

Range 应该可以折叠

0

评论者:amalloy

是的,应该可以。现在是时候深入研究折叠实现啦!

0

评论者:amalloy

我应该把这些提交都整合到一个里吗?我不知道 JIRA 上的偏好是什么,也不知道 range/iterate 是否应该是可迭代的,或者我是否应该删除第二个提交。

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 在核心中。它们是来源,不是转换器,只有转换器(它们必须与基于 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 等实现的宏,这些都是基于 (.seq this),它将是一个 LazySeq。然而,这似乎是一个有些尴尬的方法,我有点不愿意在 core.clj 中滥用。如果有人有更好的替代方法,我将很高兴听到。在目前,我将继续使用这个宏实现,以防它最终被证明是最好的选择。

0

评论者:amalloy

此补丁涵盖了之前针对本问题以及 CLJ-992 的所有补丁--

为了创建一个既是延迟序列又是可缩短源的对象,我需要向 core_deftype 添加一个名为 defseq 的宏。
这基本上是 clojure.lang.LazySeq 的一个 clojure 宏实现,这样我就可以将延迟序列函数“混合”到需要一个新类的新方法中。
所以,它可以在需要减少和折叠的方法中“混合”。
如果我们愿意,我们可以使用这个宏在 clojure 中实现 lazy-seq,而不是在 java 中,但这与此补丁无关,所以我没有这样做。
如前所述的注释中提到的,defseq 可能不是正确的方法,但直到有更好的建议,这可以行得通。

正如先前的评论中提到的,defseq 可能不是正确的方法,但直到有更好的建议,这可以行得通。

0

评论者:amalloy

我意外地将这个补丁中的 drop-while 的一个实现包含进去,我正在玩这个来确保我理解这个实现的工作原理。我想我暂时会留在这个实现里,因为它可以工作并且很有用,但如果不需要,我可以将其删除或将它移动到新的 JIRA 工程项中。

0

评论由:richhickey 提出

好吧,我认为这个补丁已经偏离了轨道。我们必须重新考虑:touching core/deftype 和以宏的形式重新实现 lazy-seq 都不应该是可行的。range 的返回值不需要“是”一个 LazySeq,它只需要“是”一个懒序列,例如通过实现 ISeq 接口来实现,只有7个方法,而不是30个,它可以通过委托其现有的实现来实现。它还可以实现一个新接口供减少逻辑使用。clojure.lang.Range 也仍然存在,这是另一种方法。在这些事情上采取极其谨慎的方法。

0

评论者:amalloy

好吧,感谢反馈 - 我很高兴我知道最后的补丁可能是不正确的我就进了:)。我认为我需要实现LazySeq中使用的java集合接口,例如java.util.List,以避免中断像(link: 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集合接口,它大部分工作正常,但在clojure.core和clojure.lang的一些部分中有一些假设,假设序列是集合。对我来说最明显的是(例如,它在运行mvn测试时出现)是RT/toArray - 它测试集合,但从不测试ISeq,这意味着它不愿意处理不是集合的ISeq。依赖toArray(例如to-array和vec)的函数现在失败了。

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

0

评论由:richhickey 提出

如果你有时间,请在开发wiki上写下你所发现的问题、挑战和选项,那将非常有帮助(即使是简单的表格也很好)。我明白这是一项挑战性的任务,在这个阶段,我们可能应该选择更低调的reducers/range和reducers/iterate,让这两个世界分离。我希望能有一天将range统一起来,因为有很多现有的range,我们希望将它们折叠,就像我们现有的向量一样。

欢迎使用 Clojure Q&A,在这里您可以提问并从 Clojure 社区的成员那里获得答案。
...