Elm Game of life 程序变得无响应 - 有没有办法优雅地失败?

Elm Game of life program becomes unresponsive - is there a way to fail gracefully?

我在 uminokirin.com.

有一个用榆树 运行 编写的 Conway 生命游戏的基本实现

来源可见here

该程序允许用户调整环形网格的大小、单击单元格以更改其状态以及随机化世界。它适用于我计算机上的小值(小于 50)。

然而,当尝试在更大的网格上使用随机化网格功能时(阈值似乎并不总是相同的),程序会在没有任何警告的情况下变得无响应,唯一的恢复方法是重新加载应用程序.

GOL 算法中存在零优化并且对每个单元格使用单个 svg 矩形可能效率极低,但它仍然不能解释为什么程序以这种方式运行而不是说,减慢吃下。

这是榆树运行时放弃了吗?或者某种浏览器保护措施?

更重要的是,除了任意限制网格的最大大小之外,还有什么方法可以防止这种行为?

您观察到的行为是由于 Javascript 堆栈溢出造成的。按下 "randomize" 按钮后,在浏览器控制台中您可以看到消息 "Uncaught RangeError: Maximum call stack size exceeded"

发生这种情况是因为随机化函数分配了几个大的临时变量。特别是,shuffle 函数(从 randomize 函数调用)似乎分配了两个临时列表,每个列表都有一个元素用于生命网格中的每个单元格。 Elm 在及时发布这些方面可能很聪明,但这似乎太过分了。

要解决此问题,您可以使用更简单的随机化函数。下面显示的版本使用 Elm 生成器生成单个 Dead/Alive 值列表,然后从该列表初始化随机数组。

randomize2 : Array Cell -> Int -> Int -> Int -> Array Cell
randomize2 grid gs sd n = 
  let floatGen = Random.float 0.0 1.0
      lifeGen = Random.map (\b -> if (b < toFloat n/100) then Alive else Dead) floatGen
      listGen = Random.list (gs*gs) lifeGen
  in fst (Random.step listGen (initialSeed sd)) |> fromList

使用这个随机化函数,我能够将网格大小调整到 600x600 并成功随机化。那时我停止了测试。