出于好奇,我在弗雷格尝试了这段代码:
println (mydrop 30000000 [1..30000001])
毋庸置疑,一个3000万条目的序列有点愚蠢,我对OOME也没问题。我想看看懒惰评估是否会在这里产生影响。结果是我的所有8个核心都以100%耗尽并留在那里直到我硬杀了这个过程。
我是否达到了系统上限?
我应该提到我使用了真实世界Haskell练习中的mydrop:
mydrop n xs = if n <= 0 || null xs
then xs
else mydrop (n-1) (tail xs)
答案 0 :(得分:2)
现在正在追踪这个问题,但事实证明,由于JVM中缺少适当的尾调用,所有情况都无法避免。请参阅此处获取解释:https://github.com/Frege/frege/issues/65
有趣的是,下面的“等效”groovy程序(我的第一个!)表现出一种有趣的行为:
println (new IntRange(0,30_000_000).drop(29).take(3))
这需要比
更长的时间println (new IntRange(0,30_000_000).drop(29_999_990).take(3))
Frege程序始终需要n+m
个步骤,其中n是已删除项目的数量,m是所采用项目的数量,因此第一个几乎是立即的,但第二个需要2到3个。在继续drop
之前,grOH计划似乎实际上意识到take
之后仍然存在的列表。因此第一个版本较慢。
答案 1 :(得分:1)
我没有意识到上限。 REPL中的一个简短测试(try.frege-lang.org)显示我可以进入
drop 16_000_000 [1..16_000_000]
仅在几秒钟后完成。由于这个程序是O(n)我估计30万的最大执行时间可能是30秒,但是在32_000_000之后我会在几秒钟之后得到“服务不可用”,这通常暗示了免费Web服务的一些限制的用尽
此外,无论数量多少,上述程序的内存使用量应保持不变。如果没有,我会认为它是一个错误。
---编辑---
在2核心的2.9GHz办公电脑上试用它:像魅力一样,需要5.7秒。 6400万人需要10.5s