请在 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是否应该是seqable,还是我应该只放弃第二个提交。

0

评论由:richhickey 发表

是的,请合并它们,否则很难看清楚(我几乎看不懂目前的差异:)。在reducers中,range和iterate不应该有创新之处,而应该增强核心函数的返回值。增强(例如协议扩展)可以通过要求reducers来实现,因为不使用它就无法利用。此外,我对为'splittable'分配协议的看法也不确定——到目前为止我已经避免这样做。

0

评论者:amalloy

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

我并不完全明白你所指的分配协议是什么。我明白你的观点,我的fold-by-halves函数(它接受一个函数)与一个只有一个函数的协议类似,但它并没有比foldvec更多分配——我只是把这种逻辑抽出来,这样就不需要在任何可折叠的东西中重复ford/join的复杂操作。你有其他的建议吗,或者这只是让你感到不安的事情,你还在考虑吗?

0

评论由:richhickey 发表

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

0

评论由:stuart.sierra 发表

如果文件包含多个提交能更清楚地表达意图,则优先选择一个大的补丁文件。

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

0

评论者:amalloy

将迭代和范围移动到core.clj中比预期的要困难。我的计划是只需让他们实现Seqable即可,这足够简单,但实际上它们是ISeq的实例,因为它们继承自LazySeq。大量的代码到处都依赖于它们是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
宏重新实现,这样我就可以将lazy-sequence函数“混合”到新的类中
以任何需要的用于归约和折叠的方法。

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

如前一个注释中所述,defseq可能不是正确的方法,但只要没有更好的建议,它就可以工作。

0

评论者:amalloy

我在这个补丁中意外地包含了一个名为drop-while的实现,我曾用它来确保我理解这所有的工作原理。我想我会暂且将其保留,因为它可行且有用,但如果它现在不被需要,我可以将其删除或将其移至新的JIRA任务中。

0

评论由:richhickey 发表

好的,我觉得这个补丁已经越界了。肯定有更好的方法。让我们从:放弃touch core/deftype和作为宏重新实现lazy-seq开始。range的返回值不一定是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测试时出现)是RT/toArray - 它测试集合,但从未测试ISeq,这意味着它不愿处理不是集合的ISeq。依赖于toArray的函数(如to-array和vec)现在失败了。

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

0

评论由:richhickey 发表

如果您有时间,请在dev wiki上总结您发现的问题、挑战和选项(即使是简单的表格也极好)。我意识到这是一项具有挑战性的任务,现在我们可能应该选择更为适度的reducers/range和reducers/iterate,并将两个世界分开。我将来希望统一range,因为有许多现有的range可以被折叠,就像现有的vector一样。

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