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