2

出于好奇,我在 Frege 中尝试了这段代码:

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)
4

2 回答 2

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 秒。奇怪的程序 OTOH 似乎实际上意识到了之后剩下的列表drop,然后再继续take。因此第一个版本较慢。

于 2014-02-11T22:07:19.850 回答
1

我知道没有上限。REPL (try.frege-lang.org) 中的一个简短测试表明我可以达到

drop 16_000_000 [1..16_000_000]

仅在几秒钟后完成。由于这个程序是 O(n),我估计 3000 万的最大执行时间可能是 30 秒,但是对于 32_000_000,我会在几秒钟后得到“服务不可用”,这通常暗示免费网络服务的某些限制已用尽.

此外,上述程序的内存使用量应该是恒定的,与数量无关。如果不是,我会认为这是一个错误。

- - 编辑 - -

在 2 核 2.9GHz 办公 PC 上试用:效果非常好,耗时 5.7 秒。6400万需要10.5s

于 2013-09-30T10:01:24.803 回答