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

欢迎!有关如何使用本页面的更多信息,请参阅关于页面。

0
Clojure

Rich 今天在IRC中提到,他很乐意看到 clojure.core/range 的一个减法器实现。现在,我已经想通了如何进行迭代,我想在这晚上也将 range 完成掉。只是提前打开问题,向任何感兴趣的其它人宣布我的意图。

24 个答案

0

评论者:amalloy

实现范围。附上一份单独的提交,让 iterate 和 range 也成为 Seqable,因为我不知道这是否是期望的。按需应用或取消。

0

评论者:jasonjckn

范围应该是可折叠的

0

评论者:amalloy

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

0

评论者:amalloy

我应该把所有这些提交合并成一份吗?我不知道 JIRA 上更喜欢哪种方式,也不知道 range/iterate 是否应该是 seqable 或我只是取消第二个提交。

0

评论者:richhickey

是的,请将它们合并在一起,否则很难看出(我几乎看不懂差异:

范围和迭代在reducers中不应该是新的,而应该是增强核心函数的返回值。增强(例如协议扩展)可以通过需要reducers来实现,因为没有它可以利用。另外,我对为'splittable'分配的协议持保留态度 - 我至今为止一直避免这种做法。

0

评论者:amalloy

所以你想让 clojure.core/range 返回某种对象(Range),该对象实现了 Counted 和 Seqable(但不仅仅是 lazy-seq),然后在 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参数,并根据(.seq this)实现ISeq、Collection等的实现,这将是一个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

行,我认为这个补丁已经偏离了正确的轨道。必须有一种更好的方法。我们先从以下几个问题开始讨论: touching core/deftype 以及将 lazy-seq 作为宏重新实现的方案已被摒弃。range 函数的返回值不必一定是 LazySeq,它可以是延迟序列,例如实现 ISeq (7种方法,而不是30种),它可以通过现有的实现进行扩展。它还可以实现一些新的接口,供 reduce 逻辑使用。此外,clojure.lang.Range 仍然存在,这是另一种方法。请在这些方面采取极其保守的态度。

0

评论者:amalloy

好的,感谢你的反馈——我很高兴在我知道上次补丁可能错误的情况下进行更改:《)。我以为我需要实现 LazySeq 的 java 集合接口,比如 java.util.List,以避免破坏诸如 (defn range-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 test 时),RT/toArray 测试 Collection,但从未测试 ISeq,这意味着它不愿意处理既不是集合又不是 ISeq 的序列。依赖于 toArray 的函数(例如 to-array 和 vec)现在失败了。

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

0

评论者:richhickey

如果时间允许,您能 somewhere 在 dev wiki 上整理出您发现的问题、挑战和选项,这将非常有帮助(即使是简单的表格也很好)。我明白这是一个具有挑战性的任务,也许现在我们应该选择更为低调的reducers/range 和 reducers/iterate,并保持两个世界的分离。我希望在某个时刻统一 range,因为有许多现存的 range,能够将其折叠,就像我们的现存向量一样。

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