繁体   English   中英

类似于功能 Scala 中的 for-loop

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM