[英]Similar to for-loop in functional Scala
我想创建一个模拟 model 来学习 Scala 以及函数式编程(FP)。 我已经有了所有的逻辑:创建一组代理(它只是一个List[Agent]
,其中Agent
是一个 class 定义一个单独的成员,就像气体中的粒子)和一些功能(例如在太空中移动)对人口的“行动”。
由于 FP 中的不变性,当我想在初始总体上多次应用相同的函数时,我的问题就出现了。 我想将这些函数应用于 N 轮的初始总体(在应用所有函数后定义一轮)。 我不知道如何处理轮次之间的不可变值。
通常,我会做一个 for 循环,其中一个变量会改变它的值,但是当值是不可变的时,你如何处理呢?
我的代码现在看起来像这样:
object Main extends App {
val soc = Society(numAgents = 1000) // Create a Society
val agents = soc.initSociety() // Init the society
val movedAgents = soc.moveAgents(agents) // Move the agents
}
该方法被定义为返回List[Agent]
,因此类型始终相同。
我见过一些使用foldleft
的解决方案,但我需要将 function moveAgents 应用于它返回的内容。
您可以通过折叠获得moveAgents
的返回值。 如果你只是想调用moveAgents
方法n
次,你可以这样做
val newAgents = (1 to n).foldLeft(soc.initSociety()) { (a, i) => soc.moveAgents(a) }
这相当于在调用moveAgents
时执行 soc.moveAgents(soc.moveAgents( n
soc.moveAgents(soc.moveAgents(...(soc.initSociety())))
如果您有多个要应用的功能(每轮使用不同的功能),您可以执行相同的操作:
// n/3 because there are 3 functions
val newAgents = (1 to n/3).foldLeft(soc.initSociety()) { (a, i) => f3(f2(f1(a))) }
如果你有一个函数List
,你可以试试这个:
val fs = List(f1, f2, f3)
val newAgents = (1 to (n/fs.size)).foldLeft(soc.initSociety()){ (a, i) => fs.foldLeft(a){ (ag, f) => f(ag) } }
好吧,任何简单的 for 循环都可以很容易地重写为 tal 递归,而(尾)递归通常可以写为foldLeft
。
第一种方法,简单循环。
def stimulate(soc: Society, n: Int): List[Agent] = {
var agents = soc.initSociety()
for (i <- 0 to n) {
agents = soc.moveAgents(agents)
}
agents
}
第二种方法,递归。
(让我们删除那个var)
def stimulate(soc: Society, n: Int): List[Agent] = {
@annotation.tailrec
def loop(i: Int, agents: List[Agent]): List[Agent] =
if (i < n) loop(i + 1, agents = soc.moveAgents(agents))
else agents
loop(i = 0, agents = soc.initSociety())
}
第三种方法,折叠。
(让我们从递归中删除样板)
def stimulate(soc: Society, n: Int): List[Agent] =
(0 to n).foldLeft(soc.initSociety()) { case (agents, _) =>
soc.moveAgents(agents)
}
如果每轮之间的中间值有任何兴趣......
val rounds = List.iterate(agents, n)(f _ andThen g andThen h)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.